bluebirdjs的承诺包裹在for循环内

我有一堆用于向我的服务提供数据的函数。 我想循环通过它们中的每一个,并在其中一个返回所需的结果时立即停止。 如果第一个工作,那很好。 如果它有一个例外或数据无效,我想移动到下一个等等。

我怎么能做到这一点? 我有下面的代码:

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循环中并行运行所有的请求,所以当你find一个你喜欢的值时,其他的已经被启动了,所以没有办法“不”运行它们。 如果你不想运行其他人,你不需要并行启动它们。 所以,这将导致您在序列化请求的devise模式。 运行一个,如果不成功,运行下一个等等。

尽我所知,Bluebird没有内置的scheme来完成你所要求的function。 我能想到的最简单的事情就是使用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 }); 

奇怪的是,如果你只是自己迭代处理器,它似乎是更less的代码,也许更简单一些:

 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(); } 

如果承诺不是一个严格的约束caolan / async#eachSeries或类似可能会帮助。 就像是…

 // var Promise = require(?) // var async = require("async") handleData: asyncProviderFinder ... function asyncProviderFinder(address){ var self = this; return new Promise(function(resolve, reject){ async.eachSeries( self.listAllAvailableProviders, function iterate(provider, next){ var handler = provider; new handler().getData(address) .then( function(value){ Logger.info(value); next("abort"); // callback any error to abort future iterations return resolve(value); }) .catch( function (err){ Logger.error(err); next(); }); }, function callback(err, firstProvider){ if ((firstProvider === undefined) && !err ){ reject(""); } } ); }); }