我对新的Promise((resolve,reject)=> {[loop]})被阻塞而Promise.resolve()。then([loop])没有阻塞感到困惑

时间:2019-04-10 06:45:34

标签: javascript node.js asynchronous promise es6-promise

我使用console.time的内置功能来设置三个基准(beforeBenchmark,benchmark和afterBenchmark)。

这两个代码完全相同。但是,区别在于JS Promises API的构造。

第一个在Promise解析中包含一个循环,然后第二个在Promise中包含一个循环。

我不确定为什么第三个console.log(“ after loop”)需要花费更长的时间才能完成,所以我将其设计为异步的。谢谢您抽出宝贵的时间阅读这篇文章。

承诺解决

循环前
beforeBenchmark:0.836ms
后循环
afterBenchmark:40.987ms
基准:41.202ms

然后答应

循环前
beforeBenchmark:1.122ms
后循环
afterBenchmark:2.872ms
基准:43.705ms

我环顾了Stack Overflow,但找不到与此相关的任何答案。

第一类承诺

console.time("beforeBenchmark");
console.time("benchmark");
console.time("afterBenchmark");
console.log("before loop");
console.timeEnd("beforeBenchmark");

let i = 0;

let promise = new Promise(( resolve, reject ) =>
{
    while (i < 10000000)
    {

        i++;
    }

    resolve();

}).then(() =>
{    
    console.timeEnd("benchmark")

});

console.log("after loop");
console.timeEnd("afterBenchmark");

结果

before loop
beforeBenchmark: 0.836ms
after loop
afterBenchmark: 40.987ms
benchmark: 41.202ms

第二种承诺

console.time("beforeBenchmark");
console.time("benchmark");
console.time("afterBenchmark");
console.log("before loop");
console.timeEnd("beforeBenchmark");
let i = 0;

let promise = Promise.resolve().then(() =>
{
    while (i < 10000000)
    {
        i++;
    }

    console.timeEnd("benchmark")
});


console.log("after loop");
console.timeEnd("afterBenchmark");

结果

before loop
beforeBenchmark: 1.122ms
after loop
afterBenchmark: 2.872ms
benchmark: 43.705ms

1 个答案:

答案 0 :(得分:2)

Promise 构造函数同步运行。如果您在new Promise(...中有阻塞代码,则该代码将在构造的Promise下的下一行运行之前运行(并阻塞)。这就是为什么您的第一个摘要包含afterBenchmark: 40.987ms的原因。

另一方面,.then回调仅在清除当前事件循环后运行 (一旦所有同步代码完成运行)–就像setTimeout(fn, 0) (不是完全相同的,因为setTimeout将在事件循环的下一个迭代中运行,而不是在当前循环的末尾运行,但这相当类似)。因此,您的第二个代码中的afterBenchmark将在then运行之前,阻塞循环运行之前被记录。