DEV Community

Cover image for fetch with a timeout
stereobooster
stereobooster

Posted on

fetch with a timeout

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)

Collapse
 
codevault profile image
Sergiu Mureşan

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).

Collapse
 
stereobooster profile image
stereobooster • Edited

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"