Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can promises be used to handle really long and blocking loops in JavaScript?

Supose that I have the following for loop, which would obviously block the event loop for a while:

function somethingExpensive() {
  let i = 0;
  while (true) {
    // Something expensive...
    if (++i === 1e10) return 'Some value.'
  }
}

Can I wrap that operation (the for loop) inside a Promise, so it does not block the "main thread"?

Something like that:

function somethingExpensive() {
  return new Promise((resolve) => {
    let i = 0;
    while (true) {
      // Something expensive...
      if (++i === 1e10) resolve('Some value.');
    }
  });
}
like image 266
Luiz Felipe Avatar asked Jan 25 '23 18:01

Luiz Felipe


1 Answers

Only to a limited extent. If the expensive operation occurs in the same Javascript environment, the environment's resources will be taken up by the expensive operation, no matter whether the expensive operation occurs synchronously or asynchronously (like after a Promise.resolve). For example, the user may be unable to interact with the page while the operation is ongoing.

Use a service worker instead, so that the expensive operations take place in a completely separate environment, allowing the original page to be interacted with as normal. For example:

const workerFn = () => {
  // something expensive
  while (true) {
  }
};
const workerFnStr = `(${workerFn})();`;
const blob = new Blob([workerFnStr], { type: 'text/javascript' });
const worker = new Worker(window.URL.createObjectURL(blob));

button.onclick = () => console.log('clicked');
body {
  height: 1000px;
}
<button id="button">click</button>

The worker there will consume a LOT of resources, but the original window will remain scrollable and interactable, as desired. Without a worker, you'd either have to live with the original window being unresponsive while the expensive operation is going on, or stagger out the expensive operation into multiple inexpensive chunks that are called, for example, every 100ms. (though, even using that method, the window may not be be as responsive as one would like - using a worker is better)

like image 61
CertainPerformance Avatar answered Jan 28 '23 06:01

CertainPerformance