解释setTimeout和catch处理程序的执行顺序

我对Timer函数,微任务和事件侦听器的执行顺序有疑问:

let promise = Promise.reject("Err@!");

setTimeout(() => {
        promise.catch(er => console.log(er,"Caught !"));         // (1)
});

window.addEventListener('unhandledrejection',event => console.log("Unhandled Rejection !",event.reason));  //  (2)

// Output 
// >> Unhandled Rejection ! Err@!
// >> Err@! Caught !

在这种情况下,被拒绝的承诺在setTimeout内部被.catch()捕获之前被Unhandled Rejection事件捕获,原因是

未处理承诺错误时,发生“未处理的拒绝” 微任务队列(https://javascript.info/microtask-queue#unhandled-rejection)的结尾

现在考虑另一种情况:

let promise = Promise.reject("Err@!");

setTimeout(() => {       // (1),gets called first

    setTimeout(function () {  // (3),gets called at last,(after (2))
        promise.catch(er => console.log("caught ",er  ))
    })

});

setTimeout(function () {      // (2),gets called after (1)
    window.addEventListener('unhandledrejection',event.reason));
})

// Output 
//>>  caught  Err@!

在这种情况下,即使在第二个setTimeout中,promise也会被嵌套setTimeout中的catch处理程序捕获,即使微任务队列为空,并且窗口事件侦听器仍无法处理被拒绝的promise ...

为什么?

yiliangxiangjiao 回答:解释setTimeout和catch处理程序的执行顺序

到承诺被拒绝(未处理)时,尚未附加 unhandledrejection 处理程序,因此无法处理该情况。您可以随时随地附加.catch.then处理程序,如果Promise已被解决/拒绝,它们将立即执行(在微任务中)。

 // first example
 1) synchronous execution
  - promise rejected
  - timeout set 
  - unhandledrejection event handler attached
 2) microtasks
  - promise rejects
 3) macrotask
  - timeout triggers
    -> .catch handler gets attached
 4) microtasks
   .catch gets executed

 // second example
 1) synchronous execution
 - timers get attached
 - promise rejects
 2) microtasks
 - promise rejected
 3) macrotasks
 - timer 1 done
   - timer 3 started
 - timer 2 done 
    - unhandledrejection handler added
本文链接:https://www.f2er.com/2720039.html

大家都在问