我正在学习Promise,为了理解它我读了一些关于JavaScript的事件循环。这个article简要地介绍了事件循环的工作,例如调用堆栈,事件表和消息队列。
但我不知道调用堆栈如何处理包含' return'以及之后发生的事情。 下面是我写的一个例子,希望了解Promise如何基于事件循环工作。如果您想试一试,请参阅http://jsbin.com/puqogulani/edit?js,console。
var p1 = new Promise(
function(resolve, reject){
resolve(0);
});
p1.then(function(val){
console.log(val);
p1.then(function(){
console.log("1.1.1");
p1.then(function(){
console.log("1.1.2");
p1.then(function(){
console.log("1.1.3");
});
});
});
p1.then(function(){
console.log("1.2");
})
return 30;
//return new Promise(function(resolve, reject){
// resolve(30);
//});
})
.then(function(val){
console.log(val/2);
});
p1.then(function(){
console.log("2.1");
});
console.log("Start");
可以看出,有两个" return",使用它们中的每个将给出不同的输出顺序。具体来说,使用return 30;
时,1.1.2, 1.1.3
位于15
之后,但使用return new Promise(...)
时,1.1.2, 1.1.3
位于15
之前。那么,当代码达到两个不同的“返回”时,究竟发生了什么?
答案 0 :(得分:2)
差异在承诺解决程序的http://promisesaplus.com/中描述。
第一个返回值:
2.3.3.4如果那时不是一个函数,用x实现承诺。
第二个:
2.3.2如果x是一个承诺,则采用其状态[3.4]:
2.3.2.2如果/当x满足时,用相同的值履行承诺。
我们可以看到这已实施q.js。这是一种可能的实现,但似乎可以解释延迟:
function coerce(promise) {
var deferred = defer();
Q.nextTick(function () {
try {
promise.then(deferred.resolve, deferred.reject, deferred.notify);
} catch (exception) {
deferred.reject(exception);
}
});
return deferred.promise;
}
当从then
函数返回一个promise时,我们有两个单独的promise对象:从传递给then
的函数返回的一个,以及从then
返回的一个。这些需要连接在一起,以便解决第一个,解决第二个。这是通过promise.then(deferred.resolve, ...)
第一次延迟来自Q.nextTick
。这将在事件循环的下一次迭代中执行该函数。在commit comments中讨论了为什么需要它。
调用promise.then
会进一步延迟事件循环的一次迭代。根据规范的要求:
2.2.4 onFulfilled或onRejected在执行上下文堆栈仅包含平台代码之前不得调用。 [3.1]。
执行将类似于:
p1.then with function containing 1.1.1 is called
function containing 1.1.1 is queued
p1.then with function containing 1.2 is called
function containing 1.2 is queued
Promise resolving to 30 is returned
Q.nextTick function is queued
----------
1.1.1 is printed
p1.then with function containing 1.1.2 is called
function containing 1.1.2 is queued
1.2 is printed
Q.nextTick function is executed
promise.then(deferred.resolve, ...) is queued
----------
1.1.2 is printed
p1.then with function containing 1.1.3 is called
function containing 1.1.3 is queued
promise.then(deferred.resolve, ...) is executed
function containing val/2 is queued
----------
1.1.3 is printed
val/2 is printed