【问题标题】:Why does this example throw UnhandledPromiseRejectionWarning? [duplicate]为什么这个例子会抛出 UnhandledPromiseRejectionWarning? [复制]
【发布时间】:2019-03-22 18:40:59
【问题描述】:

NodeJS 版本 8.11 - 警告是“此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。”

这些都不是真的,你可以通过检查我的测试用例看到:

const DEMONSTRATE_FAILURE = false

async function doPromises() {
    try {
        if (DEMONSTRATE_FAILURE) {
            // This causes UnhandledPromiseRejectionWarning warnings:

            const brokenPromises = [createPromises(), createPromises()]

            await brokenPromises[0]
            await brokenPromises[1]

        } else {
            // This works fine:
            await createPromises()
            await createPromises()
        }
    } catch(err) {
        process.stdout.write("x")
    }
}

// Create 10 promises, of which 50% will reject after between 0 and 1000ms
function createPromises() {
    let badPromises = []
    for (let x = 0; x < 10; x++) {
        badPromises.push(new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.5) {
                process.stdout.write("-")
                reject("rejected!")
            } else {
                process.stdout.write("+")
                resolve()
            }
        }, Math.round(Math.random() * 1000))
        }))
    }

    return Promise.all(badPromises)
}


(async function main() {
    while (true) {
        await doPromises()
    }
})()

翻转DEMONSTRATE_FAILURE 标志以查看相同代码运行时出现和未出现错误的情况。

【问题讨论】:

    标签: node.js promise async-await


    【解决方案1】:

    问题在于,一旦awaited Promise 拒绝,就会引发错误,并且代码会从try 内的await brokenPromises[0] 行移动到catch。因此,brokenPromises[0] 抛出的错误现在已被正确捕获。但是,brokenPromises[1] 中被拒绝的Promise处理! (如果try 块已经通过[0] 并到达[1],它被处理,然后await brokenPromises[0] 会抛出一个本可以被捕获的错误,但是口译员不知道)

    这是一个小得多的示例来说明您的原始问题(打开浏览器控制台以查看拒绝,它在 Stack Snippet 控制台中不可见):

    const makeProm = () => new Promise((_, reject) => setTimeout(reject, 500));
    
    console.log('will be uncaught:');
    // Unhandled rejection:
    (async () => {
      try {
        const proms = [makeProm(), makeProm()];
        await proms[0];
        await proms[1];
      } catch(e){}
    })();
    
    // Works:
    setTimeout(async () => {
      console.log('going to be caught:');
      try {
        await makeProm();
        await makeProm();
      } catch(e){ console.log('caught'); }
    }, 1000);

    您可以通过awaitPromise.allPromises 来修复它,而不是await分别Promise - 这样,当Promise.all 抛出时,两者都被拒绝Promise链子已经处理好了。

    在此处将 process.stdout.writes 更改为 console.logs,以便可以在可运行的 sn-p 中说明修复:

    const DEMONSTRATE_FAILURE = true;
    
    async function doPromises() {
      try {
        if (DEMONSTRATE_FAILURE) {
          // This causes UnhandledPromiseRejectionWarning warnings:
    
          const brokenPromises = [createPromises(), createPromises()]
          await Promise.all(brokenPromises);
    
        } else {
          // This works fine:
          await createPromises()
          await createPromises()
        }
      } catch (err) {
        console.log("x")
      }
    }
    
    // Create 10 promises, of which 50% will reject after between 0 and 1000ms
    function createPromises() {
      let badPromises = []
      for (let x = 0; x < 10; x++) {
        badPromises.push(new Promise((resolve, reject) => {
          setTimeout(() => {
            if (Math.random() > 0.5) {
              console.log("-")
              reject("rejected!")
            } else {
              console.log("+")
              resolve()
            }
          }, Math.round(Math.random() * 1000))
        }))
      }
    
      return Promise.all(badPromises)
    }
    
    
    (async function main() {
        await doPromises()
    })()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      相关资源
      最近更新 更多