【问题标题】:Why promise runs before the timeout here? [duplicate]为什么承诺在超时之前运行? [复制]
【发布时间】:2021-03-09 23:40:48
【问题描述】:

在下面的代码 sn-p 中,setTimeout 和 reject 都异步执行。我的印象是 setTimeout 推送到偶数队列,然后拒绝推送到事件队列。然后 setTimeout 庆祝并立即执行,拒绝。这意味着首先记录 6 个,然后记录 3 个,但是控制台日志让我感到震惊:

3
6

这是为什么呢?为什么要在 setTimeout 之前拒绝?

let promise = new Promise(
    function (resolve, reject) {
        setTimeout(() => {
            console.log(" 6 ");
        }, 0);
        reject(" 3 ");
        resolve(" 4 ");
    }
);
promise.then(
    function (st) {
        console.log(st);
    },
    function (st) {
        console.log(st)
    }
);

【问题讨论】:

  • setTimeout 将始终“晚于”当前代码执行。所以,这里的操作是延迟一个函数(记录6)->用3拒绝->用4解决(但承诺已经被拒绝)->/*稍后*/->记录6
  • youtube.com/watch?v=8aGhZQkoFbQ&ab_channel=JSConf 解释了js是如何工作的
  • 作业队列的优先级高于任务队列

标签: javascript node.js asynchronous promise v8


【解决方案1】:

这与Web Spec 中定义的事件循环有关。浏览器有多个任务队列,用于多种类型的任务(例如,通过 setTimeout 创建的计时器任务),以及一个微任务队列(Promise 结算被推送到的地方)。每当浏览器完成执行任务时,它会清空微任务队列并执行其中的所有任务,然后再继续执行另一个任务队列中的任务。

Timeout 和 Promises 都以异步方式执行代码,但它们有不同的目的和特性:

setTimeout 将函数的执行延迟特定的持续时间,并且不会阻塞其余代码。基本上setTimeout 安排一个宏任务。 Promise 也不会阻塞其余代码,除非您使用 await 运算符而是创建一个微任务。

由于微任务在运行下一个宏任务之前执行,Promise 将始终是 resolved/rejectedsetTimeout 之前。

现在,为了获得所需的输出,您需要将 reject() 调用移动到 setTimeout

let promise = new Promise(
    function (resolve, reject) {
        setTimeout(() => {
            console.log(" 6 ");
            reject(" 3 ");
            resolve(" 4 ");
        }, 0);
    }
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 2021-02-25
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多