承诺的动态顺序执行 [英] Dynamic sequential execution of promises

查看:120
本文介绍了承诺的动态顺序执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要按顺序运行动态数量的承诺。
我理解我如何能够按顺序执行承诺,但是我没有成功地通过许多可能变化的承诺使其变得动态。



这是我发现静态执行此操作的方法如何一个接一个地解决承诺?



  function waitFor(timeout){return new Promise(function(resolve,reject){setTimeout(function(){resolve(`Finishished waiting $ {timeout} milliseconds`);},timeout);});} waitFor(1000).then(function(result){$('#result')。append(result +'@'+(new Date()。getSeconds())+'< br>'); return waitFor(2000 );}}。然后(函数(结果){$('#result')。append(结果+'@'+(新Date()。getSeconds())+'< br>'); return waitFor(3000 );}}}。then(function(result){$('#result')。append(result +'@'+(new Date()。getSeconds())+'< br>');});  

< pre class =snippet-code-html lang-html prettyprint-override> < 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个嵌套的承诺。
你能帮帮我吗?



非常感谢!!

解决方案

有三种基本方式使用Promises实现此任务。


  1. .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(超时);  


  1. 递归模式。

  function waitFor(timeout){return new Promise(function(resolve,reject){setTimeout(function(){resolve(`finishedished 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);  


  1. 从左侧模式扫描。

scanl 模式将序列化承诺一个接一个,但一旦完成,你也可以获得临时承诺决议。在某些情况下,这可能很有用。如果您要懒惰地构造异步树结构(仅在需要时从节点分支),您需要访问先前的承诺分辨率。



为了实现JS中的 scanl 功能,首先我们必须实现它。

  var scanl =(xs,f,acc)=> xs.map((a => e => a = f(a,e))(acc))

我们用 xs 提供 scanl ,这是此特定示例中的超时数组, 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(超时,//输入数组(a,t,r)=> a.then (v =>(r = v,waitFor(t)))//回调函数.then(v =>(console.log(`$ {r}和$ {v}`),`$ {r}和$ {v}`)),Promise.resolve(`以0开头)); //累加器初始值//访问先前的子顺序resolutionPromise.all(proms).then(vs => vs.forEach(v => console.log(v)));  

  .as-console-wrapper {max-height:100%!important}  


I have a dynamic number of promises that I need to run sequentially. I understood how I can run sequentially promises but I don't succeed to make it dynamic with a number of promises that could vary.

Here is a way I found to do it statically 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>

I would like to do the same but instead of 3 nested promises, I would like to have any number I want. Can you help me ?

Thanks a lot!!

解决方案

There are three basic ways to achieve this task with Promises.

  1. .reduce() pattern.

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);

  1. The recursive pattern.

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);

  1. Scan from left pattern.

The scanl pattern would sequence promises one after another but once it is completed you also have access to the interim promise resolutions. This might be useful in some cases. If you are going to construct an asynchronous tree structure lazily (branching from the nodes only when needed) you need to have access to the previous promise resolutions.

In order to achieve scanl functionality in JS, first we have to implement it.

var scanl = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc))

we feed scanl with xs which is the array of timeouts in this particular example, f which is a callback function that takes acc (the accumulator) and e (current item) and returns the new accumulator. Accumulator values (the interim promise resolutions) are mapped over the timeouts array to be accessed when needed.

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
}

这篇关于承诺的动态顺序执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆