我有很多需要顺序执行的承诺。
我了解如何按顺序执行诺言,但是我无法通过许多可能会发生变化的诺言使它动态化。

这是我发现静态地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
}

10-04 22:29