Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bluebird.js: How to add wait for each iteration of Promise.map?

I am processing an array using Promise.map. For each element I am performing an async operation which returns a promise. However, I want to introduce some delay between each call because the downstream has a limit on the number of requests. Here is what I want to do

return Promise.map(array, function (elem){
    // perform an async call using elem
    // wait for 500 ms
})

How can I achieve the same ?

like image 668
Mandeep Singh Avatar asked Mar 08 '16 08:03

Mandeep Singh


2 Answers

because the downstream has a limit on the number of requests

The solution to this type of problem is to limit the number of simultaneous requests that you make. Using a delay would just be a guess as to how to control that, but not precise at all. Instead, you should literally limit the number of requests you have in flight at the same time.

How can I achieve the same ?

Fortunately for you, Bluebird has a concurrency option exactly for controlling how many requests are in-flight at the same time with the Promise.map() method by setting the concurrency option. Let's say you found that it was safe to have two requests in flight at the same time. Then, you could do this:

return Promise.map(array, function (elem){
    // perform an async call, return a promise from that async call
}, {concurrency: 2});

This will manage the iteration through the array so that no more than 2 async operations are in flight at the same time. You can obviously set concurrency to whatever value you find appropriate.

The Promise.mapSeries() method is a special case of Promise.map() with concurrency already set to 1. So, if you truly wanted the calls to be sequential (with only one in-flight at any given time), then you could just use the Promise.mapSeries() method instead.

like image 186
jfriend00 Avatar answered Nov 11 '22 10:11

jfriend00


Delay won't help as all items of the array are still going to be processed (or start getting processed) at the same time.

You need to set the concurrency option

return Promise.map(array, function (elem){
    // perform an async call using elem
    // wait for 500 ms
}, {concurrency: 1})
like image 44
laggingreflex Avatar answered Nov 11 '22 10:11

laggingreflex