一尘不染

正确编写承诺循环的方式。

node.js

如何正确构造一个循环以确保以下的 promise调用 和链接的 logger.log(res) 通过迭代同步运行?(蓝鸟)

db.getUser(email).then(function(res) { logger.log(res); }); // this is a promise

我尝试了以下方法(来自http://blog.victorquinn.com/javascript-promise-while-
loop的方法)

var Promise = require('bluebird');

var promiseWhile = function(condition, action) {
    var resolver = Promise.defer();

    var loop = function() {
        if (!condition()) return resolver.resolve();
        return Promise.cast(action())
            .then(loop)
            .catch(resolver.reject);
    };

    process.nextTick(loop);

    return resolver.promise;
});

var count = 0;
promiseWhile(function() {
    return count < 10;
}, function() {
    return new Promise(function(resolve, reject) {
        db.getUser(email)
          .then(function(res) { 
              logger.log(res); 
              count++;
              resolve();
          });
    }); 
}).then(function() {
    console.log('all done');
});

尽管它似乎可以工作,但是我认为它不能保证调用 logger.log(res); 的顺序

有什么建议?


阅读 264

收藏
2020-07-07

共1个答案

一尘不染

我不认为这可以保证调用logger.log(res);的顺序。

实际上,确实如此。该语句在resolve调用之前执行。

有什么建议?

很多。最重要的是您使用手动创建承诺反模式 -仅做

promiseWhile(…, function() {
    return db.getUser(email)
             .then(function(res) { 
                 logger.log(res); 
                 count++;
             });
})…

其次,该while功能可以简化很多:

var promiseWhile = Promise.method(function(condition, action) {
    if (!condition()) return;
    return action().then(promiseWhile.bind(null, condition, action));
});

第三,我不会使用while循环(带有闭包变量),而是使用for循环:

var promiseFor = Promise.method(function(condition, action, value) {
    if (!condition(value)) return value;
    return action(value).then(promiseFor.bind(null, condition, action));
});

promiseFor(function(count) {
    return count < 10;
}, function(count) {
    return db.getUser(email)
             .then(function(res) { 
                 logger.log(res); 
                 return ++count;
             });
}, 0).then(console.log.bind(console, 'all done'));
2020-07-07