Sergei
Sergei
Apr 23 · 2 min read

Some time ago I was faced with an issue downloading files with Node.js.
Since file downloading in Node.js is an asynchronous operation, this issue looked interesting for me because with javascript promises you either can download files one-by-one with ‘Promise.then’, or start to download all of them asynchronously and wait for a result with ‘Promise.all’. As far as I know, in javascript there is no native mechanism to split asynchronous tasks by several queues when queues are executed asynchronously, but tasks inside a queue are executed sequentially.

Although this issue may be something that other developers have solved with different libraries, I wanted to tackle it on my own as seemed to be more a quite specific and interesting issue to try to find a solution to - particularly since I wanted to not only spread asynchronous tasks by queues, but also to make it dependent on loaded file sizes to keep it balanced.

Adding a code to simply download a file by URL is somewhat trivial and I wouldn’t want to litter this post with it, but I would like to give some attention to the code on how to make (with javascript) an abstract pool for weighted asynchronous tasks.

Pool interface:

Pool implementation:

Queue implementation:

Potentially Queue.add can be rewritten with async/await and looping inside instead of a promises chain (stopping a cycle is more simple than a promises chain, but it also has its own positives and negatives beyond the scope of this post).

And a result of the tasks execution:

$ node tasks.js
Queue #1: task is started
Queue #2: task is started
Queue #3: task is started
Queue #4: task is started
Finishing task #4
Queue #4: task is finished
Queue #4: task is started
Finishing task #1
Queue #1: task is finished
Queue #1: task is started
Finishing task #6
Queue #1: task is finished
Queue #1: task is started
Finishing task #2
Queue #2: task is finished
Queue #2: task is started
Finishing task #3
Queue #3: task is finished
Queue #3: task is started
Finishing task #5
Queue #4: task is finished
Finishing task #9
Queue #3: task is finished
Finishing task #8
Queue #2: task is finished
Queue #2: task is started
Finishing task #10
Queue #2: task is finished
Finishing task #7
Queue #1: task is finished
All tasks are done

Many kudos for text review & comments to David Lorbiecke.

Pipedrive Developers

Stories from the developers at Pipedrive and developers who work with Pipedrive

Sergei

Written by

Sergei

Software Engineer

Pipedrive Developers

Stories from the developers at Pipedrive and developers who work with Pipedrive

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade