Skip to content

Instantly share code, notes, and snippets.

@barklund
Created January 27, 2021 16:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save barklund/1b5a9f9ee1b68d65027fb0c912e88f14 to your computer and use it in GitHub Desktop.
Save barklund/1b5a9f9ee1b68d65027fb0c912e88f14 to your computer and use it in GitHub Desktop.
Return best weather service that answers within a timed limit
function fetchWeather(services, timeout) {
let bestData = null;
const controllers = services.map(() => new AbortController());
const cancelFrom = index => controllers.slice(index).map(c => c.abort());
const fetches = services.map((url, index) =>
fetch(url, {signal: controller[index].signal})
.then((res) => {
bestData = res;
cancelFrom(index+1);
return res;
})
);
const limit = new Promise(r => setTimeout(r, timeout))
.then(() => cancelFrom(0));
return Promise.race([limit, fetches[0]])
.then(() => bestData)
};
@tcodes0
Copy link

tcodes0 commented Jan 27, 2021

I'm not sure about line 15, what if api 0 instantly rejects and all others are slow (but could return data eventually) then this would return null. Might make sense to race limit with a promise from promise.all somehow

@barklund
Copy link
Author

what if api 0 instantly rejects

Hm yeah it wouldn't actually return null, as the then() wouldn't be invoked if the race rejects, but it would throw an unhandled rejection exception. You'd need something to deal with that case, true.

@barklund
Copy link
Author

You could solve it by adding a catch handler to line 6 returning the next promise in the chain - a bit ugly, but it might work!

const fetches = services.map((url, index) =>
    fetch(url, {signal: controller[index].signal})
      .then(
        res => {
          bestData = res;
          cancelFrom(index+1);
        },
        () => services[index + 1],
      )
  );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment