可以使用promise处理JavaScript中的长循环和阻塞循环吗? [英] Can promises be used to handle really long and blocking loops in JavaScript?

查看:116
本文介绍了可以使用promise处理JavaScript中的长循环和阻塞循环吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下 for 循环,这显然会阻塞事件循环一段时间:

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.'
  }
}

我可以将该操作( for 循环)包装在Promise中,这样它不会阻塞主线程"吗?

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

类似的东西:

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

推荐答案

不,您不能单独使用promises来允许所有其他事件在事件循环中运行.这是因为ES6 +中的本机承诺是高优先级事件,并且会在其他类型的事件之前发生,因此其他类型的事件仍然会饿死.

No, you can't use promises alone to allow all other events to run in the event loop. That's because native promises in ES6+ are high priority events and will get their turn before other types of events so those other types of events can still get starved.

允许所有其他事件与循环交织的通常方法是在某个时间点使用短的 setTimeout()来控制循环的迭代,以便在迭代之间合理地存在一个延迟.循环.延迟时间短的 setTimeout()允许所有其他类型的事件转弯.

The usual way to allow all other events to interleave with your loop is to use a short setTimeout() at some point to control the iteration of the loop so that there's legitimately a delay between iterations of the loop. The setTimeout() with at least a short delay allows all other types of events to get a turn.

使用常规 for 循环执行此操作的一种方法是这样的(它使用诺言只是在内部暂停 for 循环,但是真正的事件循环帮助来了来自 delay()函数中的 setTimeout()):

One way to do this with a regular for loop is like this (which uses a promise just to internally pause the for loop, but the real event loop help comes from the setTimeout() in the delay() function):

function delay(t) {
    return new Promise((resolve) => {
        setTimeout(resolve, t);
    });
}


async function doStuff() {
  let max = 100_000_000_000_000n;

    let cntr = 1;
    for (let i = 1n; i <= max; i = i + 1n) {
        // let other stuff run once in every 100 iterations of the loop
        if (cntr % 100 === 0) {
            // give other things in the event queue a chance to run 
            // note: this use setTimeout(), not just promises
            await delay(10);  
        }
        // do the work for your loop here
    }
}    


如果您真的想将耗时的循环与事件循环处理分开,那么最好将其从同一事件循环中分离出来.在node.js中,您可以使用Worker线程,而在浏览器中,您可以使用WebWorkers.然后,它们可以通过消息传递回结果到主线程.


If you really want to separate out your time consuming loop from event loop processing, then it's best to get it out of the same event loop at all. In node.js you can use Worker threads and in the browser you can use WebWorkers. These can then communicate back results to the main thread via messaging.

这篇关于可以使用promise处理JavaScript中的长循环和阻塞循环吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆