Promise构造函数回调的主体何时执行



假设我有以下代码构建Promise:

function doSomethingAsynchronous() {
return new Promise((resolve) => {
const result = doSomeWork();
setTimeout(() => {
resolve(result);
}), 100);
});
}

在哪个时间点调用doSomeWork()?它是紧接在Promise构建之后还是在构建时?如果没有,我是否需要明确地做一些额外的事情来确保回调运行?

立即,是的,根据规范。

来自MDN:

执行器函数由Promise实现立即执行,传递解析和拒绝函数(在Promise构造函数返回创建的对象之前调用执行器)

这是在ECMAScript规范中定义的(当然,它更难阅读…)(从本次编辑开始的第9步,显示执行器被同步调用):

  1. 让完成就是完成(调用(executor,undefined,«resolvingFunctions.[[Resolve]],resolvingFunctions.[[Reject]]»))

(我的重点)

这种保证可能很重要,例如,当你准备好几个承诺,然后传递给allrace时,或者当你的执行人有同步的副作用时。

您可以从下面看到,只需将同步代码而不是异步代码放入正文中,正文就会立即执行:

function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous();
console.log("b");

结果显示promise主体立即执行(在打印"b"之前)。

承诺的结果被保留,将发布给"然后"调用,例如:

function doSomethingAsynchronous() {
return new Promise((resolve) => {
console.log("a");
resolve("promise result");
});
}
doSomethingAsynchronous().then(function(pr) {
console.log("c:" + pr);
});
console.log("b");

结果:

a
b
c:promise result

对主体中的异步代码进行相同的处理,除了在promise实现之前的不确定延迟,然后可以调用"then"(点c)。因此,一旦doSomethingAsynchronous()返回,就会打印ab,但c只有在承诺实现时才会出现(调用"resolve")。

一旦添加了对then的调用,表面上看起来很奇怪的是,即使所有内容都是同步的,b也会在c之前打印。

a肯定会打印,然后是c,最后是b

之所以按顺序打印abc,是因为无论主体中的代码是async还是syncthen方法总是由Promise异步调用。

在我看来,一旦resolve被调用,then方法就会被Promise中类似setTimeout(()=>{then(pr)},0)的东西调用。即,在执行传递给then的函数之前,当前执行路径必须完成。

Promise规范中不清楚它为什么要这样做?

我的猜测是,它确保了关于何时调用then(总是在当前执行线程完成之后)的一致行为,这可能是为了在连续启动所有then调用之前允许多个Promises堆叠/链接在一起。

是的,当您构造Promise时,第一个参数会立即执行。

一般来说,您不会像以前那样真正使用promise,就像您当前的实现一样,它仍然是同步的。

您宁愿使用超时来实现它,或者将resolve函数作为ajax回调的一部分来调用

function doSomethingAsynchronous() {
return new Promise((resolve) => {
setTimeout(function() {
const result = doSomeWork();
resolve(result);
}, 0);
});
}

setTimeout方法将在事件队列空闲的下一个可能时刻调用该函数

来自EcmaScript规范

执行器函数由Promise立即执行实现,传递解析和拒绝函数(执行器是在Promise构造函数返回创建的对象之前调用)

考虑以下代码:

let asyncTaskCompleted = true
const executorFunction = (resolve, reject) => {
console.log("This line will be printed as soon as we declare the promise");
if (asyncTaskCompleted) {
resolve("Pass resolved Value here");
} else {
reject("Pass reject reason here");
}
}
const myPromise = new Promise(executorFunction)

当我们执行上述代码时,一旦我们声明Promise,就会自动调用executorFunction,而不必显式调用它。

最新更新