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.');
}
});
}
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With