假设我有以下代码构建Promise
:
function doSomethingAsynchronous() {
return new Promise((resolve) => {
const result = doSomeWork();
setTimeout(() => {
resolve(result);
}), 100);
});
}
在哪个时间点调用doSomeWork()
?它是紧接在Promise
构建之后还是在构建时?如果没有,我是否需要明确地做一些额外的事情来确保回调运行?
立即,是的,根据规范。
来自MDN:
执行器函数由Promise实现立即执行,传递解析和拒绝函数(在Promise构造函数返回创建的对象之前调用执行器)
这是在ECMAScript规范中定义的(当然,它更难阅读…)(从本次编辑开始的第9步,显示执行器被同步调用):
- 让完成就是完成(调用(executor,undefined,«resolvingFunctions.[[Resolve]],resolvingFunctions.[[Reject]]»))
(我的重点)
这种保证可能很重要,例如,当你准备好几个承诺,然后传递给all
或race
时,或者当你的执行人有同步的副作用时。
您可以从下面看到,只需将同步代码而不是异步代码放入正文中,正文就会立即执行:
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()
返回,就会打印a
和b
,但c
只有在承诺实现时才会出现(调用"resolve")。
一旦添加了对then
的调用,表面上看起来很奇怪的是,即使所有内容都是同步的,b
也会在c
之前打印。
a
肯定会打印,然后是c
,最后是b
?
之所以按顺序打印a
、b
和c
,是因为无论主体中的代码是async
还是sync
,then
方法总是由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
,而不必显式调用它。