ES6 承诺执行顺序
ES6 promise execution order
我希望以下代码段的输出为 1, 2, 3, 4
。但是,实际的输出顺序是1, 4, 3, 2
.
self.promiseChain = new Promise(function (resolve, reject) {
setTimeout(resolve, 4000);
}).then(function () {
console.log(1);
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 3000);
}).then(function () {
console.log(2);
});
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
}).then(function () {
console.log(3);
});
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 200);
}).then(function () {
console.log(4);
});
});
http://www.es6fiddle.net/imu5bhoj/
我读到的关于 promises 的所有内容都表明应该可以在这样的 'flat' 链中获得所需的顺序。显然我错过了一些细节?有人可以帮我指明正确的方向吗?
这里有一个 fiddle (http://www.es6fiddle.net/imu6vh1o/) 说明如何以非平面方式执行此操作,但它更难推理并使顺序链接变得笨拙。
我已经搜索过关于堆栈溢出的类似问题,但 none 他们使用一个简单的例子(我能找到)一般地回答了这个问题。
您刚刚将三个 .then()
处理程序附加到完全相同的 self.promiseChain
承诺。这是分支,而不是链接。对于承诺,这些是非常不同的行为。当 self.promiseChain
被解析时,这三个处理程序将一个接一个地被调用(无需等待结果)。因此,由此产生的三个异步操作将 运行 并行并在它们完成时完成,因此您会看到结果。
如果您希望对这四个操作进行排序,那么您实际上必须将它们一个接一个地链接起来,而不是全部链接到同一个承诺上。记住 .then()
returns 一个新的承诺,它是您想要链接到的返回承诺以便对事物进行排序。
您正在这样做:
var p = somePromise();
p.then(fn1);
p.then(fn2);
p.then(fn3);
这将基本同时触发 fn1
、fn2
和 fn3
,并且 fn2
不会等待 fn1
promise 解决。
如果你想对操作进行排序,那么你需要这种类型的逻辑:
var p = somePromise();
p.then(fn1).then(fn2).then(fn3);
在 fn1
承诺完成之前不会执行 fn2
并且在 fn2
承诺完成之前不会执行 fn3
- 从而对异步操作进行排序。
如果它们真的被一个接一个地排序,情况会是这样。你实际上可以 运行 这个片段(但要有耐心,因为 运行 需要 10 秒):
var self = {};
self.promiseChain = new Promise(function (resolve, reject) {
setTimeout(resolve, 4000);
}).then(function () {
log(1);
});
var p = self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 3000);
}).then(function () {
log(2);
});
});
p = p.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
}).then(function () {
log(3);
});
});
p = p.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 200);
}).then(function () {
log(4);
});
});
p.then(function() {
// last promise is done now
log("all done");
});
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
查看其他类似答案:
我希望以下代码段的输出为 1, 2, 3, 4
。但是,实际的输出顺序是1, 4, 3, 2
.
self.promiseChain = new Promise(function (resolve, reject) {
setTimeout(resolve, 4000);
}).then(function () {
console.log(1);
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 3000);
}).then(function () {
console.log(2);
});
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
}).then(function () {
console.log(3);
});
});
self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 200);
}).then(function () {
console.log(4);
});
});
http://www.es6fiddle.net/imu5bhoj/
我读到的关于 promises 的所有内容都表明应该可以在这样的 'flat' 链中获得所需的顺序。显然我错过了一些细节?有人可以帮我指明正确的方向吗?
这里有一个 fiddle (http://www.es6fiddle.net/imu6vh1o/) 说明如何以非平面方式执行此操作,但它更难推理并使顺序链接变得笨拙。
我已经搜索过关于堆栈溢出的类似问题,但 none 他们使用一个简单的例子(我能找到)一般地回答了这个问题。
您刚刚将三个 .then()
处理程序附加到完全相同的 self.promiseChain
承诺。这是分支,而不是链接。对于承诺,这些是非常不同的行为。当 self.promiseChain
被解析时,这三个处理程序将一个接一个地被调用(无需等待结果)。因此,由此产生的三个异步操作将 运行 并行并在它们完成时完成,因此您会看到结果。
如果您希望对这四个操作进行排序,那么您实际上必须将它们一个接一个地链接起来,而不是全部链接到同一个承诺上。记住 .then()
returns 一个新的承诺,它是您想要链接到的返回承诺以便对事物进行排序。
您正在这样做:
var p = somePromise();
p.then(fn1);
p.then(fn2);
p.then(fn3);
这将基本同时触发 fn1
、fn2
和 fn3
,并且 fn2
不会等待 fn1
promise 解决。
如果你想对操作进行排序,那么你需要这种类型的逻辑:
var p = somePromise();
p.then(fn1).then(fn2).then(fn3);
在 fn1
承诺完成之前不会执行 fn2
并且在 fn2
承诺完成之前不会执行 fn3
- 从而对异步操作进行排序。
如果它们真的被一个接一个地排序,情况会是这样。你实际上可以 运行 这个片段(但要有耐心,因为 运行 需要 10 秒):
var self = {};
self.promiseChain = new Promise(function (resolve, reject) {
setTimeout(resolve, 4000);
}).then(function () {
log(1);
});
var p = self.promiseChain.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 3000);
}).then(function () {
log(2);
});
});
p = p.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 2000);
}).then(function () {
log(3);
});
});
p = p.then(function () {
return new Promise(function (resolve, reject) {
setTimeout(resolve, 200);
}).then(function () {
log(4);
});
});
p.then(function() {
// last promise is done now
log("all done");
});
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
查看其他类似答案: