【问题标题】:I am confused about new Promise((resolve, reject) => {[loop]}) is blocking while Promise.resolve().then([loop]) is not我对 new Promise((resolve, reject) => {[loop]}) 阻塞而 Promise.resolve().then([loop]) 不感到困惑
【发布时间】:2019-08-31 13:02:13
【问题描述】:

我有三个使用console.time内置函数的基准测试(beforeBenchmark、benchmark和afterBenchmark)。

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

第一个在 Promise resolve 中包含一个循环,第二个在 Promise then 中包含一个循环。

我不确定为什么第三个 console.log("after loop") 需要更长的时间才能完成,我将其设计为异步的。感谢您抽出宝贵时间阅读本文。

承诺解决

循环前
beforeBenchmark:0.836ms
循环后
基准测试后:40.987 毫秒
基准测试:41.202 毫秒

承诺然后

循环前
beforeBenchmark:1.122ms
循环后
基准测试后:2.872ms
基准测试:43.705 毫秒

我查看了 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

【问题讨论】:

  • 他们都在阻塞......虽然在不同的时间......但两者都绝对阻塞......尝试在浏览器中使循环更大......两者都会触发“脚本也正在占用长”消息

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


【解决方案1】:

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

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

【讨论】:

  • 实际上,立即解决的 Promise 是在微任务中从同一个事件循环中运行的。所以const oups = ()=&gt;Promise.resolve('too bad').then(oups); oups() 会阻塞线程,而 setTimeout 不会。
猜你喜欢
  • 2018-06-18
  • 2019-04-07
  • 1970-01-01
  • 2015-11-15
  • 2016-08-17
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 2019-10-29
相关资源
最近更新 更多