繁体   English   中英

具有setTimeout的JavaScript串行承诺

[英]JavaScript Serial Promises with setTimeout

我正在使用setTimeouts构建Promise链。 所有的Promise都需要串联而不是并行运行。 我正在使用Bluebird模块来实现Promise执行的串行流程。

有人可以解释一下为什么此代码给我输出1,2,3,4而不是4,3,2,1吗?

 var bluebirdPromise = require('bluebird'); function p1(value) { return new Promise(function(resolve, reject) { setTimeout(function(resolve) { console.log(value); resolve; }, value * 1000); }); } var arr = [p1(4), p1(3), p1(2), p1(1)]; bluebirdPromise.reduce(arr, function(item, index, length) { }).then(function (result) { }); 

有几个问题:

  • 您拥有的console.log并不依赖于先前解决的承诺。 只是超时决定了何时发生输出。 当您在“相同”时间创建所有四个Promise,因此同时调用了所有四个setTimeout调用时,它们的回调在确定的超时时被调用。 紧随其后如何链接承诺都没有关系...要解决此问题,您需要将console.log移动到then回调中,因为该回调仅在链中的先前承诺已解决时才执行。

  • 您的代码中未调用resolve函数。 您需要添加括号。

  • setTimeout回调的resolve参数隐藏具有相同名称的函数:您需要删除该参数。

这是建议的更正。 对于此代码段,我已用标准Array#reduce替换了bluebird的reduce ,但它与bluebird的reduce工作原理类似:

 function p1(value) { return new Promise(function(resolve, reject) { setTimeout(function() { // *** resolve(value); // *** }, value * 1000); }); } var arr = [p1(4), p1(3), p1(2), p1(1)]; arr.reduce(function(promise, next) { return promise.then(_ => next).then( value => { console.log(value); // *** return value; }); }, Promise.resolve()); 

如果您有一个Promise-Creator函数p ,并且要以串行方式运行一个Promise 序列 ,则无需加载一个带有Promise的数组-而是让它成为一个普通的值数组

注意,我这里也不使用value * 1000 –在您的代码中,您认为必须使用计算得出的setTimeout延迟人为地编排要按特定顺序触发的承诺。 事实并非如此。 仔细观察代码的评价下面来看看我们是如何让每个承诺之间有1秒钟的延迟和.then让事情为了

还要注意,此代码将在第一个promise解析后立即开始输出–而不是在输出所有值之前等待所有promise解析

 const p = x => new Promise(f => setTimeout(f, 1e3, x)) const arr = [4,3,2,1] arr.reduce((acc, x) => acc.then(() => p(x)).then(console.log), Promise.resolve()) 

好的,您可以按顺序运行这些承诺,但是为什么呢? 除非以后的步骤某种程度上取决于前面的步骤的结果,否则您没有理由要放慢它们的速度–即,每个诺言的结果都不依赖于其他诺言,因此,请尽可能快地计算它们。 但是您担心订单会丢失,对吗? 不用担心,一切都会好起来的-我什至会使用随机延迟向您显示,每个承诺的完成时间都无关紧要

 const p = x => new Promise(f => setTimeout(f, 1e3 * Math.random(), x)) const arr = [4,3,2,1] arr.map(p).reduce((acc, x) => acc.then(() => x).then(console.log), Promise.resolve()) 

因此,现在,所有的Promise都可以立即启动,并且第一个Promise解析后即开始输出(与Promise.all不同,Promise.all会等待所有Promise完成,然后再提供任何值)。

我只提到这是一种替代方法,因为您提供的示例表明并没有真正需要按顺序执行promise。 您可能天真地简化了问题的范围,但只有您知道情况是否如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM