有了Promise,为什么浏览器会两次返回拒绝,但不会两次返回解析?


10

我在理解javaScript时遇到了麻烦promises。我写了以下代码:

var p = new Promise(function(resolve,reject){

    reject(Error("hello world"));
});

setTimeout(()=>p.catch(e=>console.log(e)),5000);

我立即在Chrome开发者控制台中看到以下内容: 在此处输入图片说明

但是,等待5秒钟后,该消息会自动变为黑色,如下图所示: 在此处输入图片说明

我以前从未在javaScript代码和开发人员控制台之间看到过这种行为,在这里,我的javaScript代码可以在开发人员控制台中“修改现有内容”。

因此,我决定resolve通过编写以下代码来查看是否发生相同的情况:

var p = new Promise(function(resolve,reject){

    resolve("hello world");
});

setTimeout(()=>p.then(e=>console.log(e)),5000);

但是在这种情况下,我的开发者控制台要等5秒钟后才显示任何内容,然后打印到hello world

为什么在调用时将resolvereject区别开来?


额外

我也写了这段代码:

var p = new Promise(function(resolve,reject){

    reject(Error("hello world"));
});

setTimeout(()=>p.catch(e=>console.log("errors",e)),5000);
setTimeout(()=>p.catch(e=>console.log("errors 2",e)),6000);
setTimeout(()=>p.catch(null),7000);

这将导致多个输出到开发人员控制台。红色错误在时间0处出现,红色在5秒处变为带有文本的黑色errors hello world,然后在6秒钟处出现新的错误消息errors 2 hello world,然后在7秒钟处出现红色错误消息。现在我对一个reject实际被调用多少次感到非常困惑...我迷路了...


1
顺便说一句:var p = new Promise(function(resolve,reject){ reject(Error("hello world")); });可以更习惯和简洁地写成var p = Promise.reject(Error("hello world"));:-)
TJ Crowder

1
很棒的问题。
TJ Crowder

Answers:


11

哇,真酷。我以前从未见过控制台这样做。(不过,它还有其他形式的动态行为,所以...)这是发生了什么:

在第一种情况下,您的setTimeout回调代码之外的所有内容的代码执行完成,并且执行堆栈返回,因此仅“ 平台代码 ”(如Promises / A +规范所称)正在运行,而不是用户级JavaScript代码(此刻)。到那时,promise被拒绝了,没有任何东西可以处理拒绝,因此这是一个未处理的拒绝,devtools将其报告给您。

然后,五秒钟后,您的回调将运行并附加一个拒绝处理程序。在这一点上,拒绝不再被处理。显然,Chrome / V8 / devtools可以一起从控制台中删除未处理的拒绝警告。您所看到的是您通过拒绝处理程序中输出的内容console.log。如果您更快地附加了拒绝处理程序,则不会收到该未处理的拒绝错误。

履行不会发生这种情况,因为不处理履行不是错误条件。不处理拒绝是。


1
哦,有道理。我注意到FireFox处理它的方式略有不同。但是好吧,现在更有意义了。
约翰

1
我写的答案是一样的,但是您的答案非常丰富,所以我还没有发布。很好的解释!+1
自由区
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.