node.js - bluebirdjs promise 包裹在 for 循环中

标签 node.js promise bluebird

我有很多函数用于向我的服务提供数据。我想循环遍历它们中的每一个,并在其中一个返回所需结果时立即停止。如果第一个有效,那很好。如果出现异常或数据无效,我想转到下一个,依此类推。

我怎样才能实现这个目标?我有以下代码:

handleData: function(address) {
  var self = this;
  return new Promise(function (resolve, reject) {
    for (var i = 0; i < self.listAllAvailableProviders.length; ++i) {
      var handler = self.listAllAvailableProviders[i];
      new handler().getData(address)
        .then(function(value) {
          Logger.info(value);
          resolve(value);
        })
        .catch(function(err){
          Logger.error(err);
        })
    }
    reject("");
  });
}

如何修复它,使其在第一个获得正确数据后立即停止?我已通读 bluebirdjs 文档但无济于事。

编辑 我在 resolve 之后添加了 break 语句,得到了以下结果:

SyntaxError: Illegal break statement
at Object.exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:513:28)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:458:32)
at tryModuleLoad (module.js:417:12)
at Function.Module._load (module.js:409:3)
at Module.require (module.js:468:17)
at require (internal/module.js:20:19)

最佳答案

您在 for 循环中并行运行所有请求,因此当您找到一个具有您喜欢的值时,其他请求已经启动,因此无法“不”运行它们。如果您在找到一个后不想运行其他的,则不需要并行启动它们。因此,这将引导您找到一种序列化请求的设计模式。运行一个,如果不成功,则运行下一个,依此类推。

据我所知,Bluebird 中没有内置方案来执行您所要求的操作。我能想到的最简单的事情是使用 Bluebird 中的数组处理函数之一,该函数将一个接一个地序列化请求,例如 Promise.mapSeries() ,然后在找到合适的值时使用拒绝中止处理。

handleData: function(address) {
    return Promise.mapSeries(this.listAllAvailableProviders, function(handler) {
        return new handler().getData(address).then(function(value) {
            // the first success we get, we will throw with 
            // the returned value in order to stop the .mapSeries progression
            throw value;
        }, function(err) {
            // log the error, but don't let the rejection propagate so other handlers are called
            Logger.error(err);
        })
    }).then(function() {
        // nothing succeeded here, turn it into an overall rejection
        throw new Error("No getData() handlers succeeded");        
    }, function(val) {
        // reject here means we got a good value so turn it into a resolved value
        return val;
    })
}


// usage
obj.handleData().then(function(val) {
    // got value here
}).catch(function(err) {
    // no values here
});
<小时/>

奇怪的是,如果您自己迭代处理程序,代码似乎会更少,而且可能会更简单:

handleData: function(address) {
    var index = 0;
    var handlers = this.listAllAvailableProviders;
    var handlerCnt = handlers.length;

    function next() {
        if (index < handlerCnt) {
            var handler = handlers[index++];
            return new handler().getData(address).catch(next);
        } else {
            return Promise.reject(new Error("No handler found for address"));
        }
    }
    return next();
}

关于node.js - bluebirdjs promise 包裹在 for 循环中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38732588/

相关文章:

javascript - 在 .then 函数中发送多个参数

javascript - react : Cannot read property 'method()' of undefined when method is bound

javascript - socket io 将函数拆分到不同的文件中

templates - 在 Jade View 中使用 javascript 代码 - if(variable) 显示未定义而不是传递

javascript - $q.when 在 angularjs 中的目的是什么?

javascript - Promise中的Promise中的Node.js Promise

javascript - sqlite3 - 异步调用的 promise

javascript - 如何在coffeeScript中翻译Promise.try

node.js - k8s 中端口未接收到 fetch 请求

javascript - Bluebird<void> 在 return 语句中不可分配给 Bluebird<Process Instance>