Wait until all promises complete even if some rejected

前端 未结 18 1917
醉酒成梦
醉酒成梦 2020-11-21 04:55

Let\'s say I have a set of Promises that are making network requests, of which one will fail:

// http://does-not-exist will throw a TypeError
va         


        
18条回答
  •  灰色年华
    2020-11-21 05:26

    There is a finished proposal for a function which can accomplish this natively, in vanilla Javascript: Promise.allSettled, which has made it to stage 4, is officialized in ES2020, and is implemented in all modern environments. It is very similar to the reflect function in this other answer. Here's an example, from the proposal page. Before, you would have had to do:

    function reflect(promise) {
      return promise.then(
        (v) => {
          return { status: 'fulfilled', value: v };
        },
        (error) => {
          return { status: 'rejected', reason: error };
        }
      );
    }
    
    const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
    const results = await Promise.all(promises.map(reflect));
    const successfulPromises = results.filter(p => p.status === 'fulfilled');
    

    Using Promise.allSettled instead, the above will be equivalent to:

    const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
    const results = await Promise.allSettled(promises);
    const successfulPromises = results.filter(p => p.status === 'fulfilled');
    

    Those using modern environments will be able to use this method without any libraries. In those, the following snippet should run without problems:

    Promise.allSettled([
      Promise.resolve('a'),
      Promise.reject('b')
    ])
      .then(console.log);

    Output:

    [
      {
        "status": "fulfilled",
        "value": "a"
      },
      {
        "status": "rejected",
        "reason": "b"
      }
    ]
    

    For older browsers, there is a spec-compliant polyfill here.

提交回复
热议问题