按顺序运行promises:每个promise在前一个promise结束后开始

时间:2017-06-14 08:09:38

标签: javascript node.js promise q es6-promise

这个问题有很多答案,但大多数答案都会同步承诺的解决方案(即执行结束,而不是执行的开始)。

This solution假设我们已经有了一系列函数:

var funcs = [foo, bar, baz, qux];

如何在不执行函数的情况下创建此类数组?我试过这个:

var promises = [];
for (i = 0 ; i < 3, ++i){
    promises.push( someFunction(i) )
}

function someFunction(i) {
    return new Promise((resolve, reject) => {
        console.log(i);
        resolve(i);
    });
}

在for循环结束时,将填充promises数组,但someFunction已执行4次。使用Promise.allQ序列只需解析序列。

如何实现这些功能开始的真正同步?特别是:

foo().then(bar).then(baz).then(qux);

----------------------------------------------- -----------------

更新(使用异步功能的简单解决方案): 执行此操作的简单方法是使用async函数和await。有关在循环中调用promise的示例,请参阅this answer,其中每个promise将在前一个promise被解析时被调用。

2 个答案:

答案 0 :(得分:1)

问题是

promises.push( someFunction(i) )

当您填充promises数组时,每次在将someFunction值传递给.push方法之前调用{p: ..., val: ...}。所以它可以根据需要提前执行。

解决方法是不要打电话。这并不容易实现,所以我在考虑一点(但丑陋)黑客。我引入了一个对象callPromise,它包含promise函数和promise函数的值。如果要提供多个值,只需传递一个数组。 apply()方法会将其转换为函数参数。函数var promises = []; for (let i = 0 ; i < 3; ++i){ promises.push( {p: someFunction, val: i} ); } promises.push({p: anotherFunction, val: [100,33]}); promises.push( {p: someFunction, val: 4} ); function someFunction(i) { return new Promise((resolve, reject) => { console.log('someFunction, i: ' + i); resolve(i); }); } function anotherFunction(i1, i2) { return new Promise((resolve, reject) => { console.log('anotherFunction, i1: ' + i1 + ', i2: ' + i2); resolve(i); }); } function callPromise(prom) { if(Object.prototype.toString.call(prom.val) !== '[object Array]') prom.val = [prom.val]; return prom.p.apply(null, prom.val); } console.log('before loop'); let result = callPromise(promises[0]); for (let i = 1 ; i < promises.length; ++i) { result = result.then(callPromise(promises[i])); }以正确的方式处理函数的执行。

可能有人提出了更好的解决方案,但这是我能想到的快速解决方案。

以下是按顺序调用promises的示例。我已经添加了一个额外的函数(如果你有另一个函数有一个以上的参数)作为PoC。

&#13;
&#13;
@GetMapping(value = "/")
public ResponseEntity<ExampleObj> findByName(@RequestParam("name") String name) {
...
&#13;
&#13;
&#13;

答案 1 :(得分:0)

您只需要传递函数的名称,而不传递参数。 在你的例子中,你打电话

      someFunction(i) 

- 你传递参数i,所以这是一个函数调用。 您应该仅按名称推送功能。每个函数的参数是在前一个promise中解析的值。

function someFunction(i) {
    return new Promise((resolve, reject) => {
        console.log(i);
       resolve(i+1); // increase the value here
   });
}

通过这种方式,参数将传递给下一个增加1的函数。但是对于链中的第一个函数,您应该传递参数。 像

这样的东西
 someFunction(0).then(someFunction).then(someFunction)

(在此解决方案中,您不需要阵列。)