0

The array has like 100.000 elements. And when I loop over it, I noticed that the page freezes for a short period of time. I read that to avoid this I need to loop over chunks of the array inside a setTimeout call, to let the browser "breathe" in between these calls.

But what if I use promises instead of setTimeout and run them in parallel instead of one after the other? So each promise would loop over a portion of the array, and update it. Would this create unexpected issues, like the array not being updated correctly?

2 Answers 2

2

It all depends on how you implement the Promises. Just be aware that if you're calling an async function, everything up to the point where you await is still synchronous code. So if you called Promise.all on a bunch of calls to this:

async function workOnSlice(array, index, count) {
  for (let i = index; i < index + count; i++) {
    doSomethingExpensive(array[i]);
  }
}

...it would still commandeer the CPU in the same way. Also, keep in mind that Promise.all doesn't actually run any code parallel; the only thing it does is allow async waits in parallel; once waits have completed, it's still a single JS thread that runs task code.

I'd recommend using a worker process/thread instead for actual parallel processing, if possible. Or if you don't care about parallel processing and just want to yield to the event loop periodically, you could queue the items to process and have a process/wait loop.

Sign up to request clarification or add additional context in comments.

6 Comments

what if I wrap the content of that function in return new Promise((resolve, reject) => { .... }) ? will it still run in sync when called inside Promise.all() ?
Yes. The code in the new Promise body runs synchronously. You could do Promise.resolve().then(() => { <your code> }) to force your code to run in a Promise task completion which would essentially enqueue the task.
so there is no other way except using setTimeout, or worker process?
Sorry, my edit came a bit later than your comment; see above. It still is not going to run the code in parallel, but it would break the work up into separate tasks so that high-priority tasks may interleave with your processing tasks. But I believe Promise tasks are pretty high-priority so you still may be robbing your UI thread if the tasks take up a lot of CPU.
You may be interested in reading about the event loop phases in the node.js documentation.
|
1

You probably want something like this if you're not using Web Workers:

(Basing my answer of of Jacob's)

async function workOnArray(array, sliceSize) {
   let promises = []

   let sliceCount = Math.ceil(array.length / sliceSize)

   for (let i = 0; i < sliceCount; i++) {
      promises.push(workOnSlice(array, i * sliceSize, sliceSize)
   }

   return Promise.all(promises)
}

async function workOnSlice(array, index, count) {
  for (let i = index; i < Math.min(index + count, array.length); i++) {
    doSomethingExpensive(array[i]);
  }
}

3 Comments

Hm, that won't work quite right. When you call workOnSlice it'll run that loop because nothing is being awaited, so essentially this is running all of the processing work synchronously.
But all the workOnSlice calls will be placed on the event loop, right? The doSomethingExpensive call will be done on each of elements in the slice synchronously
Async functions are synchronous until the first await is encountered.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.