Skip to content

NodeJs: Timers #120

Open
Open
@yaofly2012

Description

@yaofly2012

一、refunref方法

  1. Timeout对象(setTimeout/setInterval)或则Immediate对象(setImmedicate)处于激活状态时,则EventLoop不能终止(即使Node应用已经运行完毕)。
let count = 0;
const timer = setInterval(() => {
    ++count;
    console.log(`count: ${count}`)
    if(count > 3) {
        clearInterval(timer)
    }
}, 1000)
  1. 通过调用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方法?

  1. 浏览器环境并没有unref方法,nodejs为啥引入这个方法?有什么应用场景?
  2. 并且这货对性能还有影响:

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.

  1. 总结一句话:除非你知道为啥使用unref,否则就不要它

1.3 unref的使用场景

  1. 应用定时数据上送功能(比如定时上送埋点数据,日志数据)
    一些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();
    }
});

参考

  1. Nodejs DOC Timers
  2. Unblocking Node With Unref()
  3. Calling Timeout.unref() With setTimeout() Does Not Appear To Be A Best Practice In Node.js

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions