为什么此示例引发UnhandledPromiseRejectionWarning?

时间:2018-10-18 01:51:44

标签: node.js promise async-await

NodeJS版本8.11-警告是“此错误是由于在没有catch块的情况下抛出异步函数而引起的,或者是拒绝了未经.catch()处理的诺言。”

这些都不是正确的,您可以通过检查我的测试用例来看到:

@foreach( $vehicles-> uploads as $upload)
  <img id="preview"  src="{{asset((isset($upload) && $upload->resized_name!='')?'images/'.$upload->resized_name:'images/noimage.png')}}" height="200px" width="200px"/>
  <input class="form-control" name="files[]" type="file" id="files" enctype="multipart/form-data">
  {{ csrf_field() }}
  <br/>
  <a href="javascript:changeProfile();">Add Image</a> |
  <a class="button is-outlined" href="/myads/{{$upload->id}}/delete" onclick="return confirm('Are you sure to want to delete this record?')" >Delete</a>
  <hr>
@endforeach

翻转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() } })() 标志以查看运行相同代码的有无错误。

1 个答案:

答案 0 :(得分:4)

问题在于,一旦awaitPromise被拒绝,就会引发错误,并且代码将从await brokenPromises[0]内的try行移到catch。因此,brokenPromises[0]引发的错误已被正确捕获。但是,在Promise中被拒绝的brokenPromises[1]已得到处理( )! (如果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);

您可以通过await同时Promise.all两个Promise来解决此问题,而不是await分别Promise分别修复-这样, Promise.all次抛出,两个拒绝的Promise链均已处理。

在此处将process.stdout.write更改为console.log,以便在可运行的代码段中说明此修复程序:

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()
})()