当非承诺引发错误时,为什么 Promise.all 不会拒绝?

Lak*_*kur 0 javascript error-handling promise

根据MDN

Promise.all() 方法将一个可迭代的 promise 作为输入,并返回一个解析为输入 promise 结果数组的单个 Promise。当所有输入的承诺都已解决,或者输入可迭代对象不包含承诺时,此返回的承诺将解决。它在任何输入承诺拒绝或非承诺抛出错误时立即拒绝,并且将拒绝此第一个拒绝消息/错误。

这是一个代码片段,它没有像我预期的那样按照上面的定义捕获错误:-

const promise1 = Promise.resolve(3);
const promise2 = () => {throw new Error('random error')};
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2(), promise3]).then((values) => {
  console.log(values);
}).catch(e=>console.log('Error caught',e));
Run Code Online (Sandbox Code Playgroud)

我知道如果我将其转换promise2()为返回一个拒绝的Promise,那么它将起作用。但是非承诺线呢?是不正确还是我遗漏了什么?

更新- 我得到了这种行为的答案。只是好奇非承诺根据定义抛出错误的可能情况是什么?

T.J*_*der 5

因为错误是调用之前抛出的Promise.allPromise.all对你来说,把它转化为拒绝是不可能的。

promise2在构建数组时调用,这发生在将该数组传递给Promise.all.

你的代码在这里:

Promise.all([promise1, promise2(), promise3])/*...*/
Run Code Online (Sandbox Code Playgroud)

...等效于以下内容(变量除外):

const x0 = promise1;
const x1 = promise2(); // <==== Error is thrown here
const x2 = promise3;
const array = [x0, x1, x2];
Promise.all(array)/*...*/
Run Code Online (Sandbox Code Playgroud)

要使其如您所愿,您有多种选择:

async正如TkoL在评论中指出的那样,您可以将其设为函数:

Promise.all([promise1, promise2(), promise3])/*...*/
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为async函数总是返回承诺(即使您不使用await),并且异步函数中的错误拒绝它返回的承诺。

您可以制作promise2一个thenable以便它在then被调用之前不会抛出,然后Promise.all将其转换为拒绝:

const x0 = promise1;
const x1 = promise2(); // <==== Error is thrown here
const x2 = promise3;
const array = [x0, x1, x2];
Promise.all(array)/*...*/
Run Code Online (Sandbox Code Playgroud)