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你是对的;这里只有微任务不会被阻止。更新了答案指出,添加了基于块的非阻塞实现。