【发布时间】:2017-08-06 08:01:25
【问题描述】:
假设我们有一个loop.js 文件:
longLoop().then(res => console.log('loop result processing started'))
console.log('read file started')
require('fs').readFile(__filename, () => console.log('file processing started'))
setTimeout(() => console.log('timer fires'), 500)
async function longLoop () {
console.log('loop started')
let res = 0
for (let i = 0; i < 1e7; i++) {
res += Math.sin(i) // arbitrary computation heavy operation
if (i % 1e5 === 0) await null /* solution: await new Promise(resolve => setImmediate(resolve)) */
}
console.log('loop finished')
return res
}
如果运行 (node loop.js) 输出:
loop started
read file started
loop finished
loop result processing started
timer fires
file processing started
如何在循环在后台运行时重写此代码以读取和处理文件?
我的解决方案
我想出的是这样的:
longLoop().then(res => console.log('loop result processing started'))
console.log('read file started')
require('fs').readFile(__filename, () => console.log('file processing started'))
setTimeout(() => console.log('timer fires'), 500)
async function longLoop () {
let res = 0
let from = 0
let step = 1e5
let numIterations = 1e7
function doIterations() {
//console.log(from)
return new Promise(resolve => {
setImmediate(() => { // or setTimeout
for (let i = from; (i < from + step) && (i < numIterations); i++) {
res += Math.sin(i)
}
resolve()
})
})
}
console.log('loop started')
while (from < numIterations) {
await doIterations()
from += step
}
console.log('loop finished')
return res
}
确实记录了:
loop started
read file started
file processing started
timer fires
loop finished
loop result processing started
有没有更简单、更简洁的方法来做到这一点?我的解决方案有什么缺点?
【问题讨论】:
-
目标平台是单核还是多核?这很重要,因为多核平台可以利用不阻碍事件循环的多进程解决方案。对于单核环境,虽然您的解决方案似乎足够好,但可以使用
process.nextTick之类的结构 - 所有这些都不可避免地阻碍了事件循环(这也适用于上述代码)。 -
如果它是单核的,那么你的解决方案是唯一的方法,但我认为它不会像你期望的那样工作,因为它是单线程的,并且一次只能处理 1 个任务时间
-
@ManasJayanth, @marvel308 是的,该平台是单核的(最常见的情况),我完全了解
node.js的单线程性质。你能详细说明process.nextTick吗?我看不出它有什么帮助,因为它将功能添加到事件队列的头部(如您所述,阻止其他任务)。 -
如果你真的想让
for循环逻辑与其他处理并行运行,那么把它放在一个工作进程中(可以是node.js或任何其他技术),然后让两者进程通信。这将允许操作系统真正对它们进行时间切片(无论是单 CPU 还是多 CPU)。 -
为什么有些人在这里声称核心数量在任何方面都很重要?您似乎不了解多线程的工作原理。实际上,单核和多核系统之间的唯一区别是性能。
标签: javascript node.js asynchronous background-task event-loop