6

Surprisingly google had trouble returning the result for this question.

I'm wondering how many promises can or should be ran in parallel before queuing them and waiting for the next one to finish. I guess it might depend on the user's internet, but I figured it was worth asking.

If it's based on the user's ISP/connection type is there a way to test for the ideal amount of promises to send before starting a queue?

Also, I'm talking strictly from the client side. So, single thread js.

Example code:

    function uploadToServer(requestData){
    return Promise((...));
   }

 function sendRequests(requestArray){
    var count = 0;
    for(var requestData in requestArray){
        if(count<idealAmount){
            uploadToServer(idealAmount).then(count--);
            count++;
       }else{
           // Logic to wait before attempting to fire event
       }

   }
 }
Larry
  • 365
  • 4
  • 12
  • `depend on the user's internet` not all promises are network based. They're just asynchronous. Maybe you should clarify that in your post. – kemicofa ghost Jan 08 '19 at 14:34
  • parallel or concurrent? node is single threaded. – ayxos Jan 08 '19 at 14:37
  • @ayxos Technically concurrent. I apologize. From my understanding if you just keep sending promises they will work concurrently. I'm wondering if there is a way to optimize sending several. Thanks for pointing that out. Words do have meaning. – Larry Jan 08 '19 at 15:23

2 Answers2

7

Promises themselves have no particular coded limits. They are just a notification system and you could have millions of them just fine (as long as you had enough memory to hold those Javascript objects).

Now, if a promise represents an underlying asynchronous operation (which they usually do), there could very well be some limits to how many of that specific type of asynchronous operation can be in flight at the same time. For example, at some point you might run into limits of how many requests a single host would accept from you at the same time. Or, you might run into local resources issues with zillions of connections somewhere.

For things like node.js disk I/O operations, the underlying disk I/O sub-system already has a queuing system so that only a small number of operations are actually running at once and the rest are queued.

So, to answer a question about how many concurrent operations you can have, it can only be analyzed and answered in the context of a specific type of asynchronous request and sometimes even a specific type of receiving host.

If you know you're processing a large or potentially large array of requests and you'll be sending a network request for every item in the array, then it is common to code a limit yourself to avoid overwhelming either local resources or the target host resources. This is usually not done with a queue, but rather code that just launches N requests and then as one finishes, it launches the next one and so on. Both the Bluebird and Async libraries have methods for managing this for you. In Bluebird, it's the concurrency option for Promise.map(). I've also hand-coded loops that manage the number of concurrent connections several times myself and here are links to some of that code:

Promise.all consumes all my RAM

Javascript - how to control how many promises access network in parallel

Make several requests to an API that can only handle 20 request a minute

Loop through an api get request with variable URL

Choose proper async method for batch processing for max requests/sec

Nodejs: Async request with a list of URL

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

As @jfried00 mentioned there can't be any limits on a number of promises running, as there's no such thing as running a Promise. Once you run an async function or run a code like new Promise(res => something(res)), the method is run.

What you can do is limit the number of promise chains being resolved:

// ten promises ago:
let oldPromise = doSomethingAsync();

// and now:
oldPromise.then(doSomethingNewAsync());

But actually coding this on your own is gonna dye your hair grey rather quickly as my example has shown - error handling, finding the empty slots and keeping the flow in the right order will be hard.

That said it is possible and my framework, Scramjet, which I'll shamelessly plug here does what you need:

DataStream.from(requestArray)
    .setOptions({maxParallel: 4})
    .unorder(requestData => uploadToServer(requestData))
    .run()

Scramjet will keep 4 promises resolving but won't try to keep order (there are other methods for that) and you can use any function - if it doesn't return a promise, it will work the same as if it did. Here's some more text on unordered transforms in scramjet. You can also peek at the source code if you'd rather do that yourself...

Michał Karpacki
  • 2,588
  • 21
  • 34