为什么 .catch() 不会在异步函数循环内的 Promise 构造函数中捕获 reject() 除非传递错误?

Why does .catch() not catch reject() within Promise constructor within loop at an async function unless Error is passed?

给定

(async () => {
 const p = await new Promise((resolve, reject) => setTimeout(() => {
    reject(new Error(1))
  }, Math.floor(Math.random() * 1000))); return p})()
.then(data => console.log(data))
.catch(err => console.error(err));

Error() 记录在 .catch()

如果我们扩展模式以使用循环,Error 将记录在 .catch()

const fn = async(res, ...props) => {
  for (let prop of props) res.push(await prop())
  return res
}

const arr = [
  () =>
    new Promise((resolve, reject) => 
      setTimeout(() =>
        reject(new Error(1))
      , Math.floor(Math.random() * 1000))
    ),
  () => 
    new Promise((resolve, reject) => 
      setTimeout(() => 
        resolve(1) 
      , Math.floor(Math.random() * 1000))
    )
  ];

fn([], ...arr)
.then(data => console.log(data))
.catch(err => console.log(err));

如果我们使用一个循环来调用多个 returns 一个 Promise 的函数并且没有显式地将 Error() 传递给 reject() of Promise构造函数 resolver 函数 .catch() 没有捕捉到错误,并且数组 res 没有返回,只有传递给 resolve()Promise 值在 [=39] 可用=]

const fn = async(res, ...props) => {
  for (let prop of props) res.push(await prop())
  return res
}

const arr = [
  () =>
    new Promise((resolve, reject) => 
      setTimeout(() =>
        reject(1)
      , Math.floor(Math.random() * 1000))
    ),
  () => 
    new Promise((resolve, reject) => 
      setTimeout(() => 
        resolve(1) 
      , Math.floor(Math.random() * 1000))
    )
  ];

fn([], ...arr)
// what happened to our array `res` returned from `fn`?
.then(data => console.log(data))
// what happened to our rejected Promise?
.catch(err => console.log(err)); 

问题:

  1. Error() 未显式传递给 Promise 构造函数中的 reject() 时,为什么 reject() 调用不会传播到 .catch() async 函数处的循环?

  2. 为什么只有一个 Promise 值返回到 .then(),尽管当 Promise 之一时从 async 函数返回一个数组在循环中迭代的对象 reject() 函数在 Promise 构造函数中被调用 resolver 函数?

If we […] do not explicitly pass Error() to reject() of Promise constructor resolver function .catch() does not catch the error

当然可以,因为那时没有错误。但是 catch 会捕获您传递给 reject 的任何内容,即值 1,它会被正确记录。

当尝试代码时,例如使用 Promise,并且预期在 .catch() 处记录错误,显式传递 Error(),最好将相关消息作为参数, 到 Promise 构造函数的 reject()Promise.reject();并使用 console.error() 代替 .catch() 处的 console.log(),以区分您希望记录为 Error() 而不是已解决的 Promise 的错误] 值,其中解析值和拒绝值可能恰好相同。