Qui*_*rty 17 javascript promise
我想更深入地了解Promises如何在内部工作.因此我有一些示例代码:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Run Code Online (Sandbox Code Playgroud)
这是执行此代码的链接.
正如您所预测的那样,首先解决p1,之后是p2,然后最终打印出resolv值.
但API参考声明如下:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
var p2 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve('res called')
}, 2000);
});
function chainPromises() {
return p1.then(function(val) {
console.log("p1");
return p2.then(function(val) {
console.log("p2");
return val;
});
});
}
chainPromises().then(function(val) {
console.log(val);
});
Run Code Online (Sandbox Code Playgroud)
因此,知道什么时候执行"then"函数会很有趣?因为代码中的最后一个"then"链接到chainPromises(),我首先想到它会在函数chainPromises()返回一些东西后执行(在这种情况下是另一个promise).
如果是这种情况,那么最终"then"函数的"val"将是返回的promise.但相反,最终的"然后"等待,直到返回的第一个"然后"内的所有承诺都已解决.这绝对有道理,因为通过这种方式,"then"函数可以堆叠,但我不知道如何完成这个,因为API规范.并没有真正涵盖"then"返回的内容以及执行"then"函数的时间.
或者换句话说,为什么最后的"then"函数会等到所有Promise在chainPromises()函数内解析,而不是像API文档所说的那样等待第一个返回的对象.
我希望我能说清楚我的意思.. :)
Ben*_*aum 12
你在这里见证的东西叫做递归then
分辨率.Promises/A +规范中的promise解析过程包含以下子句:
onFulfilled或onRejected返回值x,运行Promise Resolution Procedure [[Resolve]](promise2,x)
ES6承诺规范(承诺展开)包含类似的条款.
这要求当一个resolve
操作发生时:在promise构造函数中,通过调用Promise.resolve
或在你的情况下在一个then
链中,一个promise实现必须递归地解包返回的值,如果它是一个promise.
这意味着if onFulfilled
(then
)返回一个值,尝试自己"解析"promise值,从而递归地等待整个链.
这意味着以下内容:
promiseReturning().then(function(){
alert(1);
return foo(); // foo returns a promise
}).then(function(){
alert(2); // will only run after the ENTIRE chain of `foo` resolved
// if foo OR ANY PART OF THE CHAIN rejects and it is not handled this
// will not run
});
Run Code Online (Sandbox Code Playgroud)
例如:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ throw Error(); });
}).then(function(){
alert("This will never run");
});
Run Code Online (Sandbox Code Playgroud)
然后:
promiseReturning().then(function(){
alert(1);
return Promise.resolve().then(function(){ return delay(2000); });
}).then(function(){
alert("This will only run after 2000 ms");
});
Run Code Online (Sandbox Code Playgroud)
这是承诺规范过程中备受争议的话题,第二个没有表现出这种行为的链式方法已被讨论但是已经决定(仍然可以在Chrome中使用,但很快就会删除).你可以在这个esdescuss线程中阅读有关整个辩论的内容.此行为是出于实际原因,因此您不必手动执行此操作.
值得一提的是,其他语言不这样做,Scala中的未来或C#中的任务都没有这个属性.例如,在C#中,您必须调用Task.Unwrap
一个任务才能等待其链解析.
让我们从一个简单的角度开始:"chainPromises"返回一个承诺,所以你可以这样看待它:
// Do all internal promises
var cp = chainPromises();
// After everything is finished you execute the final "then".
cp.then(function(val) {
console.log(val);
});
Run Code Online (Sandbox Code Playgroud)
一般来说,当返回从"那么"条款中的承诺,封装承诺的"那么"功能将被完成内部"然后"完成后,才显着.
所以,如果"a"是承诺,"b"是承诺:
// "a"'s "then" function will only be marked as finished after "b"'s "then" function has finished.
var c = a.then(function () {
return b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Run Code Online (Sandbox Code Playgroud)
所以输出将是:
B!
Done!
Run Code Online (Sandbox Code Playgroud)
请注意,如果您没有"返回"内部承诺,情况就不是这样了:
// "a"'s "then" function will only be marked as finished without waiting for "b"'s "then" to finish.
var c = a.then(function () {
// Notice we're just calling b.then, and don't "return" it.
b.then(function () {
console.log("B!");
};
};
// c is a promise, since "then" always returns a promise.
c.then(function() {
console.log("Done!");
};
Run Code Online (Sandbox Code Playgroud)
在这里,我们不知道先输出什么.它可能是"B!" 或"完成!".
归档时间: |
|
查看次数: |
7615 次 |
最近记录: |