I'm trying to get some data from a server with fetch request. Some times network will fail or similar other things happens and I want to have a timeout to prevent further errors and also have a better experience.
Actually I want to wait for 20 seconds and if I don't get any response I want to show an error and also break the fetch request.
I have a loading modal which I can close it by timeout but I want to break the fetch request either.
here is my fetch request code:
_testPress = async () => {
//setTimeout(() => {this.setState({loading: false})}, 20000)
this.setState({loading : true})
fetch(getInitUrl('loginUser'), {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
password : this.state.password,
email : this.state.emailAddress,
}),
}).then(response => Promise.all([response.ok, response.status ,response.json()]))
.then(([responseOk,responseStatus, body]) => {
if (responseOk) {
//console.log(responseOk, body);
this._signInAsync(body.token);
// handle success case
} else {
console.log(responseStatus);
this.setState({
showAlert : true,
alertType : true,
alertMessage : body.message
});
}
})
.catch(error => {
console.error(error);
// catches error case and if fetch itself rejects
});
}
I used setTimeout to close loading module but it wont stop actual request which I want it to stop after 20 seconds.
Please help me with your advice. thx.
There is no standard param you can add to fetch, but you can do this work around:
// creating a wrapper for promises
function timeout(milliseconds, promise) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("timeout exceeded"))
}, milliseconds)
promise.then(resolve, reject)
})
}
// using that wrapper with fetch
timeout(1000, fetch('/api'))
.then(function(response) {
// response success
}).catch(function(error) {
// timeout error or server error
})
EXAMPLES:
Timeout exceeded:
// creating a wrapper for promises
function timeout(milliseconds, promise) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("timeout exceeded"))
}, milliseconds);
promise.then(resolve, reject);
});
}
const requestErr = new Promise((resolve, reject) => {
setTimeout(() => {
// request finished.
resolve();
}, 2500);
})
timeout(1000, requestErr)
.then(function(response) {
console.log("OK!");
}).catch(function(error) {
console.log("ERROR TIMEOUT!");
});
Timeout not exceeded:
// creating a wrapper for promises
function timeout(milliseconds, promise) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("timeout exceeded"))
}, milliseconds);
promise.then(resolve, reject);
});
}
const requestOk = new Promise((resolve, reject) => {
setTimeout(() => {
// request finished.
resolve();
}, 500);
})
timeout(1000, requestOk)
.then(function(response) {
console.log("OK!");
}).catch(function(error) {
console.log("ERROR TIMEOUT!");
});
You can also use AXIOS that has its own timeout setting.
You can abort fetch request by passing "signal" into fetch options.
An AbortSignal object instance; allows you to communicate with a fetch request and abort it if desired via an AbortController.
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
Full code example is here.
https://javascript.info/fetch-abort
let controller = new AbortController();
fetch(url, {
signal: controller.signal
});
controller.abort();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With