petkaantonov / bluebird

:bird: :zap: Bluebird is a full featured promise library with unmatched performance.
http://bluebirdjs.com
MIT License
20.45k stars 2.33k forks source link

Map with concurrency and multiple catches #1130

Closed JemiloII closed 8 years ago

JemiloII commented 8 years ago

(This issue tracker is only for bug reports or feature requests, if this is neither, please choose appropriate channel from http://bluebirdjs.com/docs/support.html)

Please answer the questions the best you can:

1) What version of bluebird is the issue happening on? "bluebird": "3.3.3" 2) What platform and version? (For example Node.js 0.12 or Google Chrome 32) Node: 0.12.13 3) Did this issue happen with earlier version of bluebird? No clue. (Write description of your issue here, stack traces from errors and code that reproduces the issue are helpful)

Could we have an option to turn off the instant failover for mapping? I like to have concurrency with multiple failovers. I make request to a server with a limit on connections, so once a connection is free, then I start the next one. However, if a connection throws an error, it stops all my connections and does not run any future ones.

Promise.map(list, function (item) {
  var a, b;
  //handle variables a and b
  return Promise.join(promise1(a), promise2(b), func(resultA, resultB) {
  //do stuff with resultA and resultB
  return promise3(resultC);
});
}, { concurrency: 5 })
.each(function (resultC) {
  //do stuff
})
.catch(function (error) {
  //handle error
})
.finally(function() {
  //finally do something at the end
})

So if list had 25 items and caused 3 errors at the beginning, I'd like the catch block to handle 3 errors while the each block handles the rest of the list and keeping the concurrency limit of 5. The order does not matter.

spion commented 8 years ago

You can catch each error, converting them to values, then filter the successes and failures

function f(item) { ... }

var results = Promise.map(list, item => 
    f(item).then(result => ({result}), err => ({err})), {concurrency: 5})

var completed = results.filter(item => 'result' in item).map(item => item.result),
    errors = results.filter(item => 'error' in item).map(item => item.error)

completed.each(item => {
  // do stuff
});
JemiloII commented 8 years ago

thanks @spion I didn't know that I could catch an error in the then block.