Promise.all无效迭代抛出生成器

试图了解Javascript生成器和承诺,我已经检查他们是好的ALAX。 我需要迭代抛出承诺的协程( Promise.coroutine来自Bluebird的libray),使得按照正确的顺序执行一些承诺是很容易的。 有了这个代码(抱歉延迟的反模式,我会学习,以避免它):

 function myPromise(x,time,i){ var deferred = Q.defer(); setTimeout(() => { deferred.resolve(x + i); },time); return deferred.promise; } router.get('/', function(req, res, next) { for (var i = 0; i < 5; i++) { Promise.coroutine(function*(i) { var a = yield myPromise('a',6000,i); var b = yield myPromise('b',1000,i); console.log(a,b); })(i) .then(() => { console.log('Then'); }). catch((err) => next(err)); } }); 

控制台中的输出(几乎)是正确的:

 a0 b0 a1 b1 a2 b2 Then Then Then a3 b3 a4 b4 Then Then 

检查这一点,我的for循环似乎不好,因为一些承诺之前,由于那个承诺结束。

如果我包括if(i == 3) deferred.reject(new Error(' ERROR!!')); 在承诺中,错误只是为了这个承诺,而不是针对其他承诺而抛出的,并且在其他承诺之后抛出:

 ERROR!! a0 b0 Then a1 b1 a2 b2 Then Then a4 b4 Then 

我认为迭代for循环不会永远不是这种问题的解决scheme。 多研究一下,我试着使用Promise.allPromise.all的调用数组:

  Promise .all([ Promise.coroutine(1), Promise.coroutine(2), Promise.coroutine(3) ]) .then(() => { console.log('then'); }) .catch((err) => next(err)); 

但在这种情况下,我拿错误:

 generatorFunction must be a function 

如果我做:

 var coroutine = function* coroutine(i) { var a = yield myPromise('a',6000,i); var b = yield myPromise('b',1000,i); console.log(a,b); }; 

相同的generatorFunction must be a function

你知道这里有什么不对吗?还是有比“ Promise.all ”更好的方法来“迭代”?

非常感谢。

对于延期反模式抱歉

其实你没有在myPromise中使用延迟反模式 ,使用deferreds从setTimeout这样的callbackasynchronous函数中获得承诺是完全正确的。 你可以使用Promise构造函数,但这不是必须的。 最好的解决办法是简单的Promise.delay (Bluebird)或Q.delay (Q)当然:-)

我的循环似乎是不好的,因为一些承诺是在别人之前结束

这是因为你对协程的调用(这是asynchronous的东西)在循环内部。 如果您将循环放在生成器函数中,它将按预期工作:

 router.get('/', function(req, res, next) { Promise.coroutine(function*() { for (var i = 0; i < 5; i++) { var a = yield myPromise('a',6000,i); var b = yield myPromise('b',1000,i); console.log(a,b); console.log('Then'); } })() .catch((err) => next(err)); }); 

甚至更好:

 var run = Promise.coroutine(function*(req, res, next) { for (var i = 0; i < 5; i++) { var a = yield myPromise('a',6000,i); var b = yield myPromise('b',1000,i); console.log(a,b); console.log('Then'); } }); router.get('/', function(req, res, next) { run(req, res, next).catch(next); });