此页面的示例。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
var p1 = new Promise(function(resolve, reject){
console.log('p1');
setTimeout(resolve, 5000, "one");
});
var p2 = new Promise(function(resolve, reject){
console.log('p2');
setTimeout(resolve, 3000, "two");
});
var p3 = new Promise(function(resolve, reject){
console.log('p3');
setTimeout(resolve, 2000, "three");
});
var p4 = new Promise(function(resolve, reject){
console.log('p4');
setTimeout(resolve, 1000, "four");
});
var p5 = new Promise(function(resolve, reject){
console.log('p5');
setTimeout(resolve, 4000, "five");
});
Promise.all([p1, p2, p3, p4, p5]).then(function(value) {
console.log(value);
}, function(reason) {
console.log(reason)
});
输出
p1, p2, p3, p4, p5
所有p1-p5都会立即执行,但是我想说是否要对它进行排序。一旦p1结算,则应调用p2,然后调用p3。
我怎样才能序列/链(而不是并行)承诺而不是一次性迭代。
如果我在等待每个承诺时采用手动方法,那就会产生回调地狱。请指教。
答案 0 :(得分:3)
首先,承诺可能会也可能不会在创建后立即开始 。
(注意:通过立即,它相对于执行循环。)
在上面的代码中,p1
到p5
会在您离开当前执行循环后立即开始倒计时。
为了确保在你想要它们之前不执行promises,你必须将它们包装在一个promise生成函数中。
var p1 = function(){
return new Promise(function(resolve, reject){
console.log('p1');
setTimeout(resolve, 5000, "one");
});
};
var p2 = function(){
return new Promise(function(resolve, reject){
console.log('p2');
setTimeout(resolve, 3000, "two");
});
};
var p3 = function(){
return new Promise(function(resolve, reject){
console.log('p3');
setTimeout(resolve, 2000, "three");
});
};
var p4 = function(){
return new Promise(function(resolve, reject){
console.log('p4');
setTimeout(resolve, 1000, "four");
});
};
var p5 = function(){
return new Promise(function(resolve, reject){
console.log('p5');
setTimeout(resolve, 4000, "five");
});
};
对于上述情况,如果您已经知道您拥有的承诺数量,您可以简单地将承诺链接在一起:
p1().then(p2).then(p3).then(p4).then(p5).then(function(){
// Hurray! All done!
console.log("All done :)");
});
但是,如果您有可变数量的承诺按顺序链接,则必须使用循环(请参阅@ PitaJ'或Array.reduce
。
var arrayOfPromiseGeneratingFunctions = [p1, p2, p3, p4, p5]; // Can be of any size.
// Take the first promise-generating function as chain initializer
var initialFn = arrayOfPromiseGeneratingFunctions.shift();
// Here we're effectively doing promise chaining like the simple solution above
var finalPromise = arrayOfPromiseGeneratingFunctions.reduce(function(previousPromise, fn){
return previousPromise.then(fn)
}, initialFn());
finalPromise.then(function(){
// Last promise called
});
此解决方案适用于任意数量的顺序执行的promises,因此只要使用函数包装promise即可。
其他一些关于此实施的内容:
1.在示例中,我们将p1到p5包装成一个函数,这样它们就不会在你想要之前以任何方式执行。
2.您可以通过在promise生成函数中添加参数,将结果promise结果从一个传递到另一个。由于第一个参数实际上是最后一个承诺的解析结果。
答案 1 :(得分:1)
then
在创建时立即执行。您必须使用new Promise(function(resolve, reject){
console.log('p1');
setTimeout(resolve, 5000, "one");
}).then(() => {
console.log('p2');
setTimeout(resolve, 3000, "two");
}).then(() => {
console.log('p3');
setTimeout(resolve, 2000, "three");
}).then(() => {
console.log('p4');
setTimeout(resolve, 1000, "four");
}).then(() => {
console.log('p5');
setTimeout(resolve, 4000, "five");
});
来链接操作。
{{1}}
答案 2 :(得分:0)
您可以这样做:
function sequential(promiseArr) {
var p = Promise.resolve(), i = 0, l = promiseArr.length;
for (; i < l; i += 1) {
p = p.then(promiseArr[i]);
}
return p;
}
编辑:修正了它。会因为p
未初始化而无法启动而失败。
答案 3 :(得分:0)
让我重新解释一下你的问题。
你有一个返回承诺的函数。只有在解决了上一个承诺时,才需要使用不同的参数一次又一次地调用此函数。
让我们想象以下就是这个功能。
function getPromise(arg) {
return new Promise(function(resolve){
setTimeout(resolve, Math.random() * 10000, [arg]);
})
};
这是你的参数列表
var promiseSetup = ['apple', 'orange', 'grapes'];
你可以在这里使用包含函数的对象而不是简单的demo params。
现在我将放下逻辑,它将对每个参数重复执行上述promise函数。这将按顺序完成。
function promiseWaterfall(args, promFunc, idx) {
if (idx >= args.length)
return;
console.log('executing ' + args[idx]);
promFunc(args[idx]).then(function(){
promiseWaterfall(args, promFunc, idx + 1)
});
}
<强>解释强>
上述函数是递归的。只有当前一个获得的承诺得到解决时,它才会使用高级索引值调用自身。
另请注意,每次解析承诺时都可以执行函数。你可以制作&#34; apple&#34;像这样的苹果对象
[{arg: "apple", func: executeApple}]
然后执行此功能,我们记录控制台消息。