jaa*_*arv 76 javascript promise ember.js rsvp.js
我有一系列承诺需要按顺序运行.
var promises = [promise1, promise2, ..., promiseN];
Run Code Online (Sandbox Code Playgroud)
调用RSVP.all将并行执行它们:
RSVP.all(promises).then(...);
Run Code Online (Sandbox Code Playgroud)
但是,我怎么能按顺序运行它们呢?
我可以像这样手动堆叠它们
RSVP.resolve()
.then(promise1)
.then(promise2)
...
.then(promiseN)
.then(...);
Run Code Online (Sandbox Code Playgroud)
但问题是承诺的数量各不相同,承诺数组是动态建立的.
Esa*_*ija 129
如果你已经将它们放在一个数组中,那么它们就已经在执行了.如果你有一个承诺,那么它已经在执行.这不是承诺的关注点(IE Task在这方面与.Start()方法不同,它们不像C#)..all没有执行任何它只是返回一个承诺.
如果你有一组promise承诺返回函数:
var tasks = [fn1, fn2, fn3...];
tasks.reduce(function(cur, next) {
return cur.then(next);
}, RSVP.resolve()).then(function() {
//all executed
});
Run Code Online (Sandbox Code Playgroud)
或价值观:
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
});
Run Code Online (Sandbox Code Playgroud)
uje*_*tor 18
使用ECMAScript 2017异步函数,可以这样做:
async function executeSequentially() {
const tasks = [fn1, fn2, fn3]
for (const fn of tasks) {
await fn()
}
}
Run Code Online (Sandbox Code Playgroud)
您现在可以使用BabelJS来使用异步功能
2017年的ES7方式.
<script>
var funcs = [
_ => new Promise(resolve => setTimeout(_ => resolve("1"), 1000)),
_ => new Promise(resolve => setTimeout(_ => resolve("2"), 1000)),
_ => new Promise(resolve => setTimeout(_ => resolve("3"), 1000)),
_ => new Promise(resolve => setTimeout(_ => resolve("4"), 1000)),
_ => new Promise(resolve => setTimeout(_ => resolve("5"), 1000)),
_ => new Promise(resolve => setTimeout(_ => resolve("6"), 1000)),
_ => new Promise(resolve => setTimeout(_ => resolve("7"), 1000))
];
async function runPromisesInSequence(promises) {
for (let promise of promises) {
console.log(await promise());
}
}
</script>
<button onClick="runPromisesInSequence(funcs)">Do the thing</button>
Run Code Online (Sandbox Code Playgroud)
这将按顺序(逐个)执行给定的功能,而不是并行执行.该参数promises是一个返回的函数数组Promise.
使用上述代码的Plunker示例:http://plnkr.co/edit/UP0rhD?p = preview
第二次尝试回答,我试图在其中更具解释性:
首先,一些必要的背景,来自RSVP README:
当您从第一个处理程序返回承诺时,真正令人敬畏的部分出现了......这允许您扁平化嵌套回调,并且是承诺的主要功能,可以防止在具有大量异步代码的程序中“向右漂移”。
这正是你如何使承诺按顺序进行,通过从then应该在它之前完成的承诺中返回后面的承诺。
把这样的一组 promise 想象成一棵树,其中的分支代表顺序进程,而叶子代表并发进程,这会很有帮助。
构建这样一棵 Promise 树的过程类似于构建其他类型树的非常常见的任务:维护指向当前在树中添加分支的位置的指针或引用,并迭代地添加内容。
正如@Esalija 在他的回答中指出的那样,如果您有一组不带参数的承诺返回函数,您可以使用reduce它们为您整齐地构建树。如果您曾经为自己实现过 reduce,您就会明白在@Esailja 的回答中,reduce 在幕后所做的是维护对当前承诺 ( cur)的引用,并让每个承诺返回其then.
如果你没有一个很好的同构数组(关于它们接受/返回的参数)承诺返回函数,或者如果你需要一个比简单线性序列更复杂的结构,你可以通过维护自己构建承诺树对承诺树中要添加新承诺的位置的引用:
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();
Run Code Online (Sandbox Code Playgroud)
您可以通过使用 RSVP.all 将多个“叶子”添加到承诺“分支”来构建并发和顺序进程的组合。我因过于复杂而被低估的答案显示了一个例子。
您还可以使用 Ember.run.scheduleOnce('afterRender') 来确保在一个承诺中完成的某些事情在下一个承诺被触发之前被渲染——我的反对票太复杂的答案也显示了一个例子。
另一种方法是在原型上定义全局序列函数Promise。
Promise.prototype.sequence = async (promiseFns) => {
for (let promiseFn of promiseFns) {
await promiseFn();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以在任何地方使用它,就像 Promise.all()
例子
const timeout = async ms => new Promise(resolve =>
setTimeout(() => {
console.log("done", ms);
resolve();
}, ms)
);
// Executed one after the other
await Promise.sequence([() => timeout(1000), () => timeout(500)]);
// done: 1000
// done: 500
// Executed in parallel
await Promise.all([timeout(1000), timeout(500)]);
// done: 500
// done: 1000
Run Code Online (Sandbox Code Playgroud)
免责声明:小心编辑原型!