考虑示例1:
var prom1 = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("Prom 1 executed");
reject("Rejected");
}, 2000);
});
console.log("Before Prom 1");
window.addEventListener("rejectionhandled", function(event) {
console.log("Handled Rejection"); //never triggers
});
window.addEventListener("unhandledrejection", function(e) {
console.log("unhandledrejection");
prom1.then(null, function(err) {
console.log("Caught error");
});
});
在这种情况下,rejectionhandled
不会触发。现在考虑示例2:
var prom1 = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("Prom 1 executed");
reject("Rejected");
}, 2000);
});
console.log("Before Prom 1");
window.addEventListener("rejectionhandled", function(event) {
console.log("Handled Rejection"); //never triggers
});
window.addEventListener("unhandledrejection", function(e) {
console.log("unhandledrejection");
setTimeout(function() {
prom1.then(null, function(err) {
console.log("Caught error");
});
}, 0);
});
现在在这个例子中rejectionhandled
确实运行了。我知道它与微任务/宏任务/事件循环有关。我知道在SO上也有类似的问题,但是我似乎不能在这里应用那个解释。也许这里的解释https://stackoverflow.com/a/57261820/3429430应该意味着每当promise被捕获在unhandledrejection的处理程序中时,它不被认为是附加的在unhandledrejection的处理程序之后'的执行。
1条答案
按热度按时间ipakzgxi1#
这是因为在HTML中,在notify about rejected promises算法的步骤5.4中,要求
1.如果 pPromiseIsHandled内部槽为false,则将 p 添加到 settings object 未完成被拒绝承诺弱集
在
HostPromiseRejectionTracker(promise, "handle")
算法中,在步骤5.2中要求1.如果 settings object 未完成被拒绝承诺弱集不包含 promise,则返回
在第一种情况下,在调度事件之后,p(a.k.a promise),已经被处理了,你确实添加了一个
.then(success, failure)
处理程序,它的[[PromiseIsHandled]]
内部槽现在是true
。这样 p 就不会进入“未完成的被拒绝的promise弱集”,当JS引擎调用HostPromiseRejectionTracker(promise, "handle")
操作时,它将在引用的5.4步骤处提前退出。然而,在第二种情况下,当事件已被调度时,其
[[PromiseIsHandled]]
内部槽仍为false
,并且当调用HostPromiseRejectionTracker(promise, "handle")
操作时,它将使其到达算法的末尾,直到激发 rejectionhandled 事件为止。所以我们可以换个说法
它只在最初没有处理的拒绝(导致 unhandledrejection 事件)上触发,但随后获得了附加的处理程序 [在 * unhandledrejection * 事件得到调度之后]。