2016-08-03 41 views
1

我有一堆功能用於提供數據到我的服務。我想循環遍歷它們中的每一個,並在其中一個返回所需結果時立即停止。如果第一個工作,那很好。如果它有異常或數據無效,我想轉到下一個等等。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文檔無濟於事。

編輯 我把break聲明resolve後,我得到了這一點:

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) 
+0

您正在運行並行所有請求在'爲'循環。當你找到你喜歡的結果時,所有其他請求已經開始。您可以一次一個序列化您的請求,然後只有在您找不到您喜歡的答案時才繼續下一個請求。那是你要的嗎? – jfriend00

+0

你可以進一步解釋序列化嗎?我想要第一個成功的人,所以如果這個人不行,那就試試下一個。這是使用'sailsjs'。 – KVISH

+0

解釋一下什麼?我不知道你對我的評論有哪些不明白的地方。你想序列化你的請求(一次運行一個)嗎? – jfriend00

回答

2

您正在運行在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(); 
} 
+0

你的第二個回答是對的!也很有意義。 – KVISH

+0

@KVISH - 我也喜歡第二個,但我認爲我解決了第一個問題。 – jfriend00

0

如果承諾沒有硬約束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(""); } 
     } 
    ); 
    }); 
} 
+0

不熟悉該庫。但是,當我安裝庫和'var async = require(「async」);''時,你的代碼甚至不會運行。 – KVISH

+0

我得到的錯誤:'返回新希望(函數解析,拒絕){ ^ 語法錯誤:意外的令牌, 在Object.exports.runInThisContext(vm.js:53:16) 在Module._compile(module.js :513:28)' – KVISH

+0

'return new Promise(function(resolve,reject){})' – Seth