Javascript 在Node.js中使CPU绑定任务异步的最简单方法?

Javascript 在Node.js中使CPU绑定任务异步的最简单方法?,javascript,node.js,event-loop,Javascript,Node.js,Event Loop,试图确定一个大列表中有多少个偶数。遵循朴素的方法:迭代列表,如果找到偶数,则增加计数。示例代码: const list = [34, 1, 35, 3, 4, 8]; //This list may become really big. taking more than 3 seconds often let evenCount = 0; for (const elem of list) { if (elem % 2 === 0) { evenCount++; } } con

试图确定一个大列表中有多少个偶数。遵循朴素的方法:迭代列表,如果找到偶数,则增加计数。示例代码:

const list = [34, 1, 35, 3, 4, 8]; //This list may become really big. taking more than 3 seconds often

let evenCount = 0;

for (const elem of list) {
  if (elem % 2 === 0) {
    evenCount++;
  }
}
console.log(evenCount);
我知道这将在事件循环执行的整个过程中阻止它。试图计算内部承诺,即

const determineEvenCount = async list => {
  return new Promise((resolve, reject) => {
    let evenCount = 0;
    for (const elem of list) {
      if (elem % 2 === 0) {
        evenCount++;
      }
    }
    resolve(evenCount);
  });
};

事件循环是否仍将被阻止?如果是,如何使其解锁?

是,它将被阻止。承诺不是某种神奇的尘埃;将其洒在阻塞代码上并不会突然使其成为非阻塞代码

在你的代码中,新的承诺实际上是多余的:因为你已经声明你的函数是异步的,它已经一直返回一个承诺。是的,由于您最初的Promise Executor是同步的(您使用plain
for…of
对列表进行迭代),因此您的其余代码必须等待命令队列耗尽:

const smallerList=Object.keys([…数组(1E4)].map(编号));
const largerList=Object.keys([…数组(1E5)].map(编号));
const determineEvenCount=异步(列表)=>{
console.time('内部循环:'+list.length);
设evenCount=0;
对于(让列表中的元素){
如果(元素%2==0){
evenCount++;
}
}
console.timeEnd('内部循环:'+list.length);
console.log(evenCount);
返回偶数;
};
console.time(“计时器执行”);
设置超时(()=>{
console.timeEnd(“计时器执行”);
}, 5);
Promise.resolve()。然后(()=>{
log('Microtask execution');
});
控制台时间(“等待同步”);
确定事件数(大列表);
确定事件数(小列表);

console.timeEnd(“等待同步”)是,它将被阻止。您可以使用webWorkers,但对于如此琐碎的事情,我感觉IPC消息传递开销也会一样长。但是,在3秒钟内,这个数组有多大,你确定它需要那么长的时间吗?你可以分块执行它,每x个元素或毫秒等待一个简单的任务(例如
等待新的承诺(res=>setImmediate(res));
)。你的“不可阻塞”版本仍然非常阻塞。它只会将阻塞延迟到下一个微任务,但仍然会以相同的方式阻塞事件循环。在
console.time(“nextTask”)之间包装所有代码
设置超时(()=>{console.timeEnd(“nextTask”);})。在这个函数完成之前,我们的下一个任务不会被调用。@kaido你是对的;这里只有微任务不会被阻止。更新了答案指出,添加了基于块的非阻塞实现。