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.all
和Promise.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); });