You may know (or will learn it right now) that new Web API fetch
comes without a timeout. I guess this is because it is built more around the idea of streams.
If you, like me, want to use fetch
for AJAX(XMLHttpRequest
) you would expect it to support timeout. I googled it and indeed people have the same issue. What I noticed is that most solution built around setTimeout
and Promise.reject
, most solutions don't bother to cancel the actual request.
So I created this snippet, which will not just timeout, but also cancel the network request:
const timeoutableFetch = (url, options = {}) => {
let { timeout = 5000, ...rest } = options;
if (rest.signal) throw new Error("Signal not supported in timeoutable fetch");
const controller = new AbortController();
const { signal } = controller;
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error("Timeout for Promise"));
controller.abort();
}, timeout);
fetch(url, { signal, ...rest })
.finally(() => clearTimeout(timer))
.then(resolve, reject);
});
};
requires AbortController
. WDYT?
Top comments (2)
That is amazing! Never thought of using
setTimeout
to reject the returned promise.One question: shouldn't the timeout usually be set on the back-end? Since having it on front-end can vary in behaviour due to bad internet or whatnot (unless that is the reason for using it).
This is very good question, which I haven't asked myself - blind spot in my brain, because I got used to it.
I guess you need timeout on client-side, if server timeout is longer than you want. For example you need to upload big files to this server and as the result timeout of all endpoints increased, not just one.
The second case, is if you guard against slow network. For example 2G connections or if your server is in Europe, but users are in Australia or Japan.
And maybe you actually right and we don't need it in first place. I just thought - "hey, everybody is doing it with timeout, but without cancel. Let me share this"