Wait until all promises complete even if some rejected

前端 未结 18 1954
醉酒成梦
醉酒成梦 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:33

    Benjamin Gruenbaum answer is of course great,. But I can also see were Nathan Hagen point of view with the level of abstraction seem vague. Having short object properties like e & v don't help either, but of course that could be changed.

    In Javascript there is standard Error object, called Error,. Ideally you always throw an instance / descendant of this. The advantage is that you can do instanceof Error, and you know something is an error.

    So using this idea, here is my take on the problem.

    Basically catch the error, if the error is not of type Error, wrap the error inside an Error object. The resulting array will have either resolved values, or Error objects you can check on.

    The instanceof inside the catch, is in case you use some external library that maybe did reject("error"), instead of reject(new Error("error")).

    Of course you could have promises were you resolve an error, but in that case it would most likely make sense to treat as an error anyway, like the last example shows.

    Another advantage of doing it this, array destructing is kept simple.

    const [value1, value2] = PromiseAllCatch(promises);
    if (!(value1 instanceof Error)) console.log(value1);
    

    Instead of

    const [{v: value1, e: error1}, {v: value2, e: error2}] = Promise.all(reflect..
    if (!error1) { console.log(value1); }
    

    You could argue that the !error1 check is simpler than an instanceof, but your also having to destruct both v & e.

    function PromiseAllCatch(promises) {
      return Promise.all(promises.map(async m => {
        try {
          return await m;
        } catch(e) {
          if (e instanceof Error) return e;
          return new Error(e);
        }
      }));
    }
    
    
    async function test() {
      const ret = await PromiseAllCatch([
        (async () => "this is fine")(),
        (async () => {throw new Error("oops")})(),
        (async () => "this is ok")(),
        (async () => {throw "Still an error";})(),
        (async () => new Error("resolved Error"))(),
      ]);
      console.log(ret);
      console.log(ret.map(r =>
        r instanceof Error ? "error" : "ok"
        ).join(" : ")); 
    }
    
    test();

提交回复
热议问题