I have a bunch of functions used to provide data to my service. I want to loop through each of them and stop as soon as one of them returns the desired result. If the first one
You are running all your requests in parallel in the for
loop so when you find one that has a value you like, the others have already been started so there's no way to "not" run them. If you want to not run the others once you've found one, you need to not start them in parallel. So, that would lead you to a design pattern where you serialize the requests. Run one, if it doesn't succeed, run the next and so on.
As best I can tell, there isn't a built-in scheme in Bluebird for doing what you're asking. The simplest thing I can think of is to use one of the array processing functions in Bluebird that will serialize the requests one after the other such as Promise.mapSeries()
and then use a rejection to abort the processing when you found a good value.
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
});
Curiously enough, it seems to be less code and perhaps a bit simpler if you just iterate the handlers yourself:
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();
}