Reputation: 443
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.
Upvotes: 3
Views: 12991
Reputation: 53
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();
Upvotes: 2
Reputation: 2190
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.
Upvotes: 2
Reputation: 636
Fetch doesn't implement a connection timeout. You can't abort a fetch request either.
Take a look at this gist, which wraps a Promise.race
around the fetch request. The promise will resolve as soon as one of the promises (the fetch or the timeout) resolves or rejects:
https://gist.github.com/davej/728b20518632d97eef1e5a13bf0d05c7
Something like this should work:
Promise.race([
fetch(getInitUrl('loginUser'), *...fetchparams* ),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), 7000)
)
]).then(*stuff*).catch(*stuff*)
Alternatively, you can also give axios a try, an alternative to fetch, with support for timeouts: https://github.com/axios/axios
Upvotes: 1