我有很多需要顺序执行的承诺。
我了解如何按顺序执行诺言,但是我无法通过许多可能会发生变化的诺言使它动态化。
这是我发现静态地How to resolve promises one after another?的一种方法:
function waitFor(timeout) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(`Finished waiting ${timeout} milliseconds`);
}, timeout);
});
}
waitFor(1000).then(function(result) {
$('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
return waitFor(2000);
}).then(function(result) {
$('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
return waitFor(3000);
}).then(function(result) {
$('#result').append(result+' @ '+(new Date().getSeconds())+'<br>');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="result"></div>
我想做同样的事情,但我希望有任意数量的而不是3个嵌套的Promise。
你能帮助我吗 ?
非常感谢!!
最佳答案
使用Promises可以完成三种基本方法。.reduce()
模式。
function waitFor(timeout) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(`Finished waiting ${timeout} milliseconds`);
}, timeout);
});
}
var timeouts = [1000, 2000, 2000, 3000, 1000],
sequence = tos => tos.reduce((p,c) => p.then(rp => waitFor(c))
.then(rc => console.log(`${rc} @ ${new Date().getSeconds()}`)), Promise.resolve());
sequence(timeouts);
递归模式。
function waitFor(timeout) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(`Finished waiting ${timeout} milliseconds`);
}, timeout);
});
}
var timeouts = [1000, 2000, 2000, 3000, 1000],
sequence = ([to,...tos]) => to !== void 0 && waitFor(to).then(v => (console.log(`${v} @ ${new Date().getSeconds()}`), sequence(tos)));
sequence(timeouts);
从左侧图案扫描。
scanl
模式将一个接一个地对承诺进行排序,但是一旦完成,您还可以访问临时承诺解决方案。在某些情况下这可能很有用。如果要懒惰地构造异步树结构(仅在需要时才从节点分支),则需要访问以前的promise解析。为了在JS中实现
scanl
功能,首先我们必须实现它。var scanl = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc))
我们向
scanl
提供xs
(在此特定示例中为超时数组),f
这是一个回调函数,该函数采用acc
(累加器)和e
(当前项)并返回新的累加器。累加器值(临时承诺解决方案)映射到超时数组上,以便在需要时进行访问。function waitFor(timeout) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(`finished waiting ${timeout} milliseconds`);
}, timeout);
});
}
var timeouts = [1000, 2000, 2000, 3000, 1000],
scanl = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc)),
proms = scanl(timeouts, // input array
(a,t,r) => a.then(v => (r = v, waitFor(t))) // callback function
.then(v => (console.log(`${r} and ${v}`),
`${r} and ${v}`)),
Promise.resolve(`Started with 0`)); // accumulator initial value
// Accessing the previous sub sequential resolutions
Promise.all(proms)
.then(vs => vs.forEach(v => console.log(v)));
.as-console-wrapper {
max-height: 100% !important
}