我怎样才能按顺序执行promise的数组?
我有一系列的承诺,需要按顺序运行。
var promises = [promise1, promise2, ..., promiseN];
调用RSVP.all将并行执行它们:
RSVP.all(promises).then(...);
但是,我怎样才能顺序运行它们?
我可以像这样手动堆叠它们
RSVP.resolve() .then(promise1) .then(promise2) ... .then(promiseN) .then(...);
但是问题是promise的数量是不一样的,promise的数组是dynamic的。
如果你已经有一个数组,那么他们已经在执行。 如果你有承诺,那么它已经在执行了。 这不是承诺的关注(IE浏览器它们不像C# Task
在这方面用.Start()
方法)。 .all
不执行任何事情只是返回一个承诺。
如果你有一个promise返回函数的数组:
var tasks = [fn1, fn2, fn3...]; tasks.reduce(function(cur, next) { return cur.then(next); }, RSVP.resolve()).then(function() { //all executed });
或值:
var idsToDelete = [1,2,3]; idsToDelete.reduce(function(cur, next) { return cur.then(function() { return http.post("/delete.php?id=" + next); }); }, RSVP.resolve()).then(function() { //all executed });
使用ECMAScript 2017asynchronous函数,可以这样做:
async function executeSequentially() { const tasks = [fn1, fn2, fn3] for (const fn of tasks) { await fn() } }
您现在可以使用BabelJS来使用asynchronousfunction
第二次尝试的答案,我试图更加解释:
首先,一些必要的背景,从RSVP自述 :
当你从第一个处理程序返回一个承诺时,真的很棒的部分来了…这可以让你平滑嵌套的callback,并且是承诺的主要function,可以防止有很多asynchronous代码的程序“向右漂移”。
这正是你如何做出连续的承诺,通过then
应承诺的承诺返回。
将这样一组承诺看作一棵树,其中分支表示顺序进程,叶子表示并发进程是有帮助的。
build立这样一个承诺树的过程类似于构build其他types的树的常见任务:维护一个指针或引用到树中您正在添加分支的位置,并迭代地添加事物。
正如@Esailija在他的回答中指出的那样,如果你有一个不带参数的promise返回函数的数组,你可以使用reduce
来整齐地为你构build树。 如果你曾经为自己实施过减免,那么你会明白,@ Esailija的回答在幕后做了什么,是保持对当前承诺( cur
)的引用,并且每个承诺都会在then
答应下一个承诺。
如果你没有一个很好的齐次数组(相对于他们所接受/返回的参数)承诺返回函数,或者如果你需要一个比简单的线性序列更复杂的结构,你可以通过维护来构build承诺树对您希望添加新承诺的承诺树中的位置的引用:
var root_promise = current_promise = Ember.Deferred.create(); // you can also just use your first real promise as the root; the advantage of // using an empty one is in the case where the process of BUILDING your tree of // promises is also asynchronous and you need to make sure it is built first // before starting it current_promise = current_promise.then(function(){ return // ...something that returns a promise...; }); current_promise = current_promise.then(function(){ return // ...something that returns a promise...; }); // etc. root_promise.resolve();
您可以通过使用RSVP.all来为承诺“分支”添加多个“树叶”来构build并发和顺序进程的组合。 我低调的存在 – 太复杂的答案就是一个例子。
您也可以使用Ember.run.scheduleOnce('afterRender')来确保在下一个承诺被触发之前,在一个承诺中完成的事情得到了呈现 – 我的低估为过于复杂的答案也显示了一个例子。
我将在这里留下这个答案,因为当我来到这里寻求解决我的问题时,这将帮助我。
我后来的事情本质上是mapSeries …我正好映射保存在一组值…我想要的结果…
所以,就我所知,FWIW帮助其他人在未来寻找类似的东西。
(请注意,上下文是一个烬应用程序)
App = Ember.Application.create(); App.Router.map(function () { // put your routes here }); App.IndexRoute = Ember.Route.extend({ model: function () { var block1 = Em.Object.create({save: function() { return Em.RSVP.resolve("hello"); }}); var block2 = Em.Object.create({save: function() { return Em.RSVP.resolve("this"); }}); var block3 = Em.Object.create({save: function() { return Em.RSVP.resolve("is in sequence"); }}); var values = [block1, block2, block3]; // want to sequentially iterate over each, use reduce, build an array of results similarly to map... var x = values.reduce(function(memo, current) { var last; if(memo.length < 1) { last = current.save(); } else { last = memo[memo.length - 1]; } return memo.concat(last.then(function(results) { return current.save(); })); }, []); return Ember.RSVP.all(x); } });
所有需要解决的是for
循环:)
var promises = [a,b,c]; var chain; for(let i in promises){ if(chain) chain = chain.then(promises[i]); if(!chain) chain = promises[i](); } function a(){ return new Promise((resolve)=>{ setTimeout(function(){ console.log('resolve A'); resolve(); },1000); }); } function b(){ return new Promise((resolve)=>{ setTimeout(function(){ console.log('resolve B'); resolve(); },500); }); } function c(){ return new Promise((resolve)=>{ setTimeout(function(){ console.log('resolve C'); resolve(); },100); }); }
我有类似的问题,我做了一个顺序运行function的recursionfunction。
var tasks = [fn1, fn2, fn3]; var executeSequentially = function(tasks) { if (tasks && tasks.length > 0) { var task = tasks.shift(); return task().then(function() { return executeSequentially(tasks); }); } return Promise.resolve(); };
如果您需要收集这些function的输出:
var tasks = [fn1, fn2, fn3]; var executeSequentially = function(tasks) { if (tasks && tasks.length > 0) { var task = tasks.shift(); return task().then(function(output) { return executeSequentially(tasks).then(function(outputs) { outputs.push(output); return Promise.resolve(outputs); }); }); } return Promise.resolve([]); };
ES7在2017年的方式。
<script> var funcs = [ _ => new Promise(res => setTimeout(_ => res("1"), 1000)), _ => new Promise(res => setTimeout(_ => res("2"), 1000)), _ => new Promise(res => setTimeout(_ => res("3"), 1000)), _ => new Promise(res => setTimeout(_ => res("4"), 1000)), _ => new Promise(res => setTimeout(_ => res("5"), 1000)), _ => new Promise(res => setTimeout(_ => res("6"), 1000)), _ => new Promise(res => setTimeout(_ => res("7"), 1000)) ]; async function runPromisesInSequence(promises) { for (let promise of promises) { console.log(await promise()); } } </script> <button onClick="runPromisesInSequence(funcs)">Do the thing</button>
这将按顺序(逐个)执行给定的function,而不是并行执行。 参数promises
是一个返回Promise
的函数数组。
与上面的代码Plunker示例: http ://plnkr.co/edit/UP0rhD?p=preview