我有一个返回promise的库中的函数。我需要多次运行此函数,但每次迭代必须等到上一个任务完成。
我的假设是我能做到这一点:
promiseReturner(1)
.then(promiseReturner(2)
.then(promiseReturner(3)
.then(...)
使用循环可以简化:
var p = Promise.resolve();
for (var i=1; i<=10; i++) {
p = p.then(promiseReturner(i));
}
但是,当我这样做时,链中的每个承诺都会同时执行,而不是.then()
似乎意味着一个接一个地执行。很明显,我遗漏了一些关于承诺的基本信息 - 但在阅读了几篇教程和博客文章后,我仍然迷失了。
答案 0 :(得分:23)
您的“非循环”解决方案也不应该起作用。您必须将函数传递给.then
,而不是承诺:
var p = Promise.resolve();
for (var i=1; i<=10; i++) {
(function(i) {
p = p.then(function() {
return promiseReturner(i);
});
}(i));
}
如果该函数返回一个promise,那么你就会得到那个链接效果。
有关MDN上的承诺的更多信息。
可以使用let
(和箭头功能)进行简化:
var p = Promise.resolve();
for (let i=1; i<=10; i++) {
p = p.then(() => promiseReturner(i));
}
或.bind
(即ES5):
var p = Promise.resolve();
for (var i=1; i<=10; i++) {
p = p.then(promiseReturner.bind(null, i));
}
答案 1 :(得分:2)
如果您使用的是es6,则可以使用array.reduce
实现此目的。我觉得很整洁。
const functions = [/* array of functions which return promises */];
const finalPromise = functions.reduce(async (promise, asyncFn) => {
await promise;
return asyncFn();
}, Promise.resolve());
答案 2 :(得分:1)
您可以使用async/await
使用es6生成器和co等库。
co(function* () {
while(upto < 10) {
var result = yield Promise.resolve(true);
}
return result;
}).then(function (value) {
console.log(value);
}, function (err) {
console.error(err.stack);
});
以下是一些详细信息:http://davidwalsh.name/async-generators
答案 3 :(得分:1)
这是我用来解决同样问题的解决方案:
var recursiveFunction = function(values) {
return new Promise(function(resolve, reject) {
if (values.length <= 0) {
return resolve();
} else {
return promiseReturner(values[0]).then(function() {
values.shift();
return recursiveFunction(values).then(function() {
resolve();
});
});
}
});
}
recursiveFunction([1,2]).then(function(r) {
console.warn('Finished solving promises sequentially');
})
答案 4 :(得分:0)
相对于彼此同步执行Promise可能很棘手。我在下面提供了一个使用Axios Promise的示例,但是您可以将其替换为自己的Promise。祝你好运!
past_tense=[]
for i in words:
if i[-1]=='e':
words.append('d')
else:
words.append('ed')
past_tense=words
答案 5 :(得分:-1)
您可以通过nsynjs运行代码,它会暂停每个返回promise的函数的执行,并等到promise被解决:
var promiseReturner = function(i) {
return new Promise(function(resolve, reject) {
setTimeout(function(){
resolve("result is "+i)
}, 1000);
});
};
function synchronousCode() {
for (var i=1; i<=10; i++) {
var p=promiseReturner(i); // nsynjs will pause here until promise is resolved
console.log(p.data); // `data` will contain result of the promise
}
};
nsynjs.run(synchronousCode, null, function(){
console.log("finish");
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>