Open
Description
一、ref
和unref
方法
Timeout
对象(setTimeout
/setInterval
)或则Immediate
对象(setImmedicate
)处于激活状态时,则EventLoop不能终止(即使Node应用已经运行完毕)。
let count = 0;
const timer = setInterval(() => {
++count;
console.log(`count: ${count}`)
if(count > 3) {
clearInterval(timer)
}
}, 1000)
- 通过调用
unref
方法可以让EventLoop的终止不依赖激活状态的Timeout
/Immedicate
对象。
it's a way to tell Node.js not to hold the current process open if the given timer is the only thing left to execute on the event-loop queue
let count = 0;
const timer = setInterval(() => {
++count;
console.log(`count: ${count}`)
if(count > 3) {
clearInterval(timer)
}
}, 1000).unref();
- 当EventLoop终止后,
Timeout
的异步任务也被取消了。
1.2 干嘛要使用unref
方法?
- 浏览器环境并没有
unref
方法,nodejs为啥引入这个方法?有什么应用场景? - 并且这货对性能还有影响:
Calling timeout.unref() creates an internal timer that will wake the Node.js event loop. Creating too many of these can adversely impact performance of the Node.js application.
- 总结一句话:除非你知道为啥使用
unref
,否则就不要它。
1.3 unref
的使用场景
- 应用定时数据上送功能(比如定时上送埋点数据,日志数据)
一些Dashboard
,log
工具里能看到它的身影。
但是有些工具会这样处理:
应用退出时,若队列中尚有未发送的埋点数据时,会自动开启一个额外的进程用户发送(windows 系统可能会看到一个命令行窗口一闪而过,不会影响应用本身)
process.on('exit', function() {
let queueFile = path.resolve(os.tmpdir(), 'XXX' + pm2.id + '-' + (+new Date()) + '.json');
let queueLength = queue.saveToDisk(queueFile);
if (queueLength) {
let subProcFile = path.resolve(__dirname, './libs/subProcSender.js');
let env = util.copy(process.env);
env.__APP_CONFIG_FILE__ = XXXX;
spawn(argWrapper(process.execPath), [argWrapper(subProcFile), argWrapper(queueFile)], {
env: env,
detached: true,
stdio: 'ignore',
shell: true
}).unref();
}
});