How can I limit angular $ q prom concurrency?

How do I do something like $q.all , but limiting the number of promises is done at the same time?

My question is similar to How can I limit the promise of Q concurrency?

I want no more than 5 processes generated at a time

The accepted answer for this other question is a library written for promise , wrapped up to work with Q. But I'm only interested in the solution for Angular $q , and not for Q

Background: Problem solved:
I have a bunch of files to upload in 2 steps: a) Get the URL b) download the file.
The browser limits the number of files that can be received at the same time, so when using promises directly with $q.all disables all downloads, only N happens immediately, for example. 6 in Chrome, and the rest with a delay. (see Maximum number of concurrent HTTP connections in a browser? )
The problem is that the URLs expire, so by the time the browser downloads the file N + 1 th the URL is no longer valid.
So I want to do something like throttled.all(6, promises) , not $q.all(promise)

+5
source share
4 answers

I think you could do something recursive.

This will allow you to use only $q . You just need to have a list that you will use, which you need anyway for $q.all

 self.MakeCall = function(theList, chunkSize){ //Split list into what will be processed and what should be held var processList = theList.slice(0,chunkSize); var holdList = theList.slice(chunkSize); return $q.all(processList).then(function(result) { //If holdList is empty you are finished if(holdList <= 0) { return result; } else { //More items make recursive call to process next set return self.MakeCall(holdList, chunkSize); } }); }; //Initialize Recursive call self.MakeCall(self.contacts); 
0
source

Here is an alternative solution that will run parallel chunks. This is not as clean as another answer, but it is closer to what you are looking for.

I left some markup used for verification.

 self.list [...]; self.MakeCall = function(theList, chunkSize,methodTracker){ //Set default chunkSize chunkSize = (chunkSize)?chunkSize:1; //Slice list using previously defined list // so multiple instances can be runuse same list var processList = self.list.slice(0,chunkSize); self.list = self.list.slice(chunkSize); return $q.all(processList).then(function(result) { //If holdList is empty you are finished if(self.list <= 0) { console.debug("method last: " + methodTracker); return result; } else { //More items make recursive call to process next set console.debug("method: " + methodTracker); return self.MakeCall(self.list, chunkSize,methodTracker); } }); }; //Initialize Recursive call self.MakeCall(self.list,1,1).then(function() { console.warn('end 1'); }); //Initialize Second call that will run asynchronous with the first // this can be initialized as many times as you want concurrent threads self.MakeCall(self.list,1,2).then(function() { console.warn('end 2'); }); 

I decided to include another answer. I think that these two are quite different, that I did not want to make changes to the other

0
source

I tried several different ways to do this, but in the end I decided to write an extension to $q , which extends its $q.all behavior with $q.allLimit() .

See angular-q-limit for details.

The module works by creating a wrapper function that takes an array from Promises and executes them in an ordered sequence (limiting parallel execution to the limit) until all are exhausted. He then resolves his own promise with the return values โ€‹โ€‹of all the same as $q.all() .

0
source

If the "all" Promises permission does not matter (for example, you are updating some elements on a page and you don't care if it is progressive, not just one whoosh), I created a simple TaskQueue service. He will not wait until all Promises are resolved, but he will process all the added Promises / Functions / Tasks that he will receive, and with max. concurrency configured limit value.

As soon as I found this and some other StackOverflow that didn't help with my problem. So now I give something back to the community, I think. Hope this helps someone.

It uses modern JS elements such as const and lambda expressions, but you can just compile it from a precompiler like babel if you just want the "old" one.

https://gist.github.com/Blackskyliner/8b1bafed326044fa4f8b1ba2627d1117

It just simply processes the turn after Tasks, which are simply anonymous functions, return a promise or value, are added. It will stick with the maxConcurrentTasks custom variable in the service.

If a task returns a promise, which returns a promise, and so on, it will always use the initial โ€œslotโ€ in the queue. Thus, he will free the โ€œslotโ€ for another added task after the whole chain of tasks is promised (or rejected).

0
source

Source: https://habr.com/ru/post/1237782/


All Articles