Skillfully use` Promise.all `Implementation function: if a promise is resolved, the whole function will be resolved

Time:2020-10-22

When calling the distributed service interface, we often encounter such a problem: the interface side provides multiple IP addresses for users to call. As long as one of them returns successfully, it will be successful.

For such a problem, a relatively simple solution is to call each interface in turn. If the previous interface fails to return, call the second interface. The advantage of this is that the consumption of server resources is relatively small, but it is very inefficient for users. Imagine calling the first interface after a 20 second timeout error before calling the second interface. If the second interface has another 20 seconds timeout, the user has already waited for 40 seconds. The waiting time of users increases linearly, which is not acceptable.

A good solution is to call all interfaces simultaneously. Some students may think of itPromise.race。 But please note: Promise.race Instead of waiting for a promise to be resolved, it will be returned as long as a promise is fulfilled, regardless of whether the promise is resolve or reject.

I’ve had similar problems,Of coursePromise.raceIt’s a trap。 You won’t use Promise.race 。 This issue has been discussed in detail in the blog postPromise.raceA solution is implemented

Promise.properRace = function properRace(promises) {
  if (promises.length < 1) {
    return Promise.reject('Can\'t start a race without promises!');
  }

  // There is no way to know which promise is rejected.
  // So we map it to a new promise to return the index when it fails
  const indexPromises = promises.map((p, index) => p.catch(e => {
    console.debug('Promise rejected in `properRace`: ' + e);
    return Promise.reject(index);
  }));

  return Promise.race(indexPromises).catch(index => {
    // The promise has rejected, remove it from the list of promises and just continue the race.
    promises.splice(index, 1)[0].catch(() => { /* eat this */ });
    return promises.length ? properRace(promises) : Promise.reject('All promises rejected');
  });
};

It’s a little complicated, but it’s really clever. I used it in my early days. Looking back recently, I suddenly thought:properRaceThe requirement is that as long as a project returned by resolve is resolved, JavaScript does not provide such a function, but it provides another similar function: as long as there is a project returned by reject, it will be rejected.

This function is very commonly used Promise.all

With this layer in mind, it’s very simple to implement properrace with it: it’s OK to switch the status of the incoming promise array forward and backward. The results were as follows:

Promise.properRace = function properRace(promises) {
  const resolve = Promise.resolve.bind(Promise);
  const reject = Promise.reject.bind(Promise);
  return Promise.all(promises.map(x => x.then(reject, resolve)))
    .then(reject, resolve);
}

finish

Updated in July 2019

This method has been standardized as Promise.any

Recommended Today

Layout of angular material (2): layout container

Layout container Layout and container Using thelayoutDirective to specify the layout direction for its child elements: arrange horizontally(layout=”row”)Or vertically(layout=”column”)。 Note that if thelayoutInstruction has no value, thenrowIs the default layout direction. row: items arranged horizontally.max-height = 100%andmax-widthIs the width of the item in the container. column: items arranged vertically.max-width = 100%andmax-heightIs the height of the […]