The Async library has functions like eachLimit which can be used to efficiently spread a big batch of jobs over multiple CPU cores, like this:
var numCPUs = require('os').cpus().length;
var exec = require('child_process').exec;
async.eachLimit(someArray, numCPUs, function (value, done) {
exec('something --input' + value, done);
}, finalCallback);
This avoids overloading the system with too many commands at once, but still exploits multiple CPUs.
I want to do the same thing but with Promises.
In the Bluebird API, I can't see any obvious way to do this kind of batching in such a concise, expressive way as with Async.
Is there a good pattern for doing this with Bluebird (or with Promises generally)? Or any other utility library I could use for this?
Assuming we have the processing power and that our promises can run in parallel, there is a hard limit of just over 2 million promises.
In single-core CPU the promises would run concurrently and in multi-core CPU they can be executed (!) in parallel for CPU intensive tasks.
all() method returns an array as an output containing promise data inside several indexes. Promise. allSettled() method returns an array of objects and each of these objects further contains two properties further status and value.
Often Promise. all() is thought of as running in parallel, but this isn't the case. Parallel means that you do many things at the same time on multiple threads. However, Javascript is single threaded with one call stack and one memory heap.
In Bluebird, you can use Promise.map
function with the concurrency
option, like this
require('bluebird').map([1, 2, 3, 4, 5, 6], function (currentNumber) {
console.log(currentNumber);
return Promise.delay(currentNumber * 2, 1000);
}, {concurrency: 2}).then(console.error.bind(console));
Now, you can see that it is processing two values at a time. The value being processed may be in a different order, but the items in the result array will be in the same order corresponding to the original array.
PS: I introduced a delay of 1 second with Promise.delay
, so that we can observe what is being processed currently.
Demo
function start() {
document.getElementById("result").innerHTML = "";
Promise.map([1, 2, 3, 4, 5, 6], function(currentNumber) {
document.getElementById("result").innerHTML += currentNumber + "<br />";
return Promise.delay(currentNumber * 2, 1000);
}, {
concurrency: parseInt(document.getElementById("concurrency").value, 10)
}).then(function(result) {
document.getElementById("result").innerHTML += result + "<br />";
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.27/bluebird.min.js"></script>
Limit: <input id="concurrency" value="2" />
<input type="button" onclick="start()" value="Start" />
<pre id="result" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With