使用setTimeout()终止Worker线程报错:Cannot read properties of undefined
为什么直接传递Worker.terminate给setTimeout会报错?
问题场景
在Node.js v18.12.0环境下,尝试用setTimeout直接调用Worker的terminate方法终止线程时触发错误,改用包装函数则能正常运行。
错误信息
node:internal/worker:361 this[kHandle].stopThread(); ^ TypeError: Cannot read properties of undefined (reading 'stopThread') at Timeout.terminate [as _onTimeout] (node:internal/worker:361:19) at listOnTimeout (node:internal/timers:564:17) at process.processTimers (node:internal/timers:507:7) Node.js v18.12.0
报错代码
const { Worker } = require("node:worker_threads") const worker = new Worker("./test.js") const setAppTimeout = (workerName, seconds) => { setTimeout(workerName.terminate, seconds * 1000) } setAppTimeout(worker, 1)
正常运行的代码
const { Worker } = require("node:worker_threads") const worker = new Worker("./test.js") const setAppTimeout = (workerName, seconds) => { setTimeout(terminateWorker, seconds * 1000, workerName) } const terminateWorker = (workerName) => { workerName.terminate() } setAppTimeout(worker, 1)
差异原因
核心问题是JavaScript的this绑定规则:
- 当你直接把
workerName.terminate作为参数传给setTimeout时,这个函数会被单独提取出来执行,此时它的this不再指向原Worker实例,而是变成了Timeout对象(或全局对象,取决于执行环境)。terminate方法内部需要通过this访问Worker的内部句柄kHandle,this指向错误就会导致无法读取kHandle,进而抛出错误。 - 用包装函数
terminateWorker时,我们通过workerName.terminate()的形式调用,此时terminate方法的this会隐式绑定到workerName这个Worker实例上,能正确访问内部的kHandle,所以可以正常终止线程。
另外还有两种等价的写法可以解决这个问题:
- 用箭头函数绑定
this:setTimeout(() => workerName.terminate(), seconds * 1000) - 用
bind手动绑定this:setTimeout(workerName.terminate.bind(workerName), seconds * 1000)
内容的提问来源于stack exchange,提问作者NoNameIdeas
相关产品推荐
相关产品推荐

