2015-02-23 45 views
16

我有一个函数返回一个承诺的库。我需要多次运行此函数,但每次迭代都必须等到上一个任务完成。你如何同步解决一系列es6承诺?

我的假设是,我可以这样做:

promiseReturner(1) 
    .then(promiseReturner(2) 
    .then(promiseReturner(3) 
    .then(...) 

这可以用一个循环被简化:

var p = Promise.resolve(); 
for (var i=1; i<=10; i++) { 
    p = p.then(promiseReturner(i)); 
} 

然而,当我在链这个每个承诺在执行同时,而不是像.then()似乎意味着一个接一个。很明显,我错过了一些有关承诺的基础知识 - 但在阅读了几篇教程和博客文章后,我仍然迷失了方向。

Here's a codepen I wrote up to demonstrate my attempt

+1

是否'promiseReturner( n)“回复承诺或履行承诺 - 返回功能? – Bergi 2015-09-04 10:32:12

回答

21

您的“非循环”解决方案也不适用。你必须一函数传递.then,而不是一个承诺:

var p = Promise.resolve(); 
for (var i=1; i<=10; i++) { 
    (function(i) { 
     p = p.then(function() { 
      return promiseReturner(i); 
     }); 
    }(i)); 
} 

如果函数返回一个承诺,那么你得到的链式效应。

有关承诺MDN的更多信息。


可与let(和箭头的功能)可以简化为:

var p = Promise.resolve(); 
for (let i=1; i<=10; i++) { 
    p = p.then(() => promiseReturner(i)); 
} 

或者.bind(这是ES5):

var p = Promise.resolve(); 
for (var i=1; i<=10; i++) { 
    p = p.then(promiseReturner.bind(null, i)); 
} 
+2

也许更清楚:“你必须通过一个函数*返回一个承诺*”? – 2015-02-23 21:03:44

+0

没关系你解释,后来在 – 2015-02-23 21:04:33

+0

我曾尝试将它包装在一个函数中[见这里](http://codepen.io/anon/pen/zxjExL?editors=001),但它似乎只运行在最后诺言。为什么封装将其封锁在自调用函数中似乎解决了这个问题? – 2015-02-23 21:16:16

1

可以使用ES6发电机和图书馆使用async/awaitco

co(function*() { 
    while(upto < 10) { 
    var result = yield Promise.resolve(true); 
    } 
    return result; 
}).then(function (value) { 
    console.log(value); 
}, function (err) { 
    console.error(err.stack); 
}); 

这里的一些细节是如何工作的:http://davidwalsh.name/async-generators

1

这里是我用来解决同样的问题的解决方案:

var recursiveFunction = function(values) { 
    return new Promise(function(resolve, reject) { 
    if (values.length <= 0) { 
     return resolve(); 
    } else { 
     return promiseReturner(values[0]).then(function() { 
      values.shift(); 
      return recursiveFunction(values).then(function() { 
       resolve(); 
      }); 
     }); 
     } 
    }); 
} 

recursiveFunction([1,2]).then(function(r) { 
console.warn('Finished solving promises sequentially'); 
}) 
0

如果您正在使用ES6,就可以实现这一点使用array.reduce 。我觉得很整齐。

const functions = [/* array of functions which return promises */]; 
const finalPromise = functions.reduce(async (promise, asyncFn) => { 
    await promise; 
    return asyncFn(); 
}, Promise.resolve()); 
-1

您可以通过nsynjs运行你的代码,它会停留在返回承诺每个函数的执行,并且将一直等到承诺解决:

var promiseReturner = function(i) { 
 
    return new Promise(function(resolve, reject) { 
 
     setTimeout(function(){ 
 
      resolve("result is "+i) 
 
     }, 1000); 
 
    }); 
 
}; 
 

 
function synchronousCode() { 
 
    for (var i=1; i<=10; i++) { 
 
     var p=promiseReturner(i); // nsynjs will pause here until promise is resolved 
 
     console.log(p.data); // `data` will contain result of the promise 
 
    } 
 
}; 
 
\t 
 
nsynjs.run(synchronousCode, null, function(){ 
 
\t console.log("finish"); 
 
});
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>