process.nextTick()的两个用途

题外话,有网友问为什么公众号叫【背井】?这里解释一下:

背井】 的 【】 读第一声,指背着井,和【坐井观天】里的【】是同一口井,作为对自己的警醒。

有些人觉得自己经历了一些事,不会再是 井底之蛙 了,其实他们不过是把井从 脚底 换到 背上 了而已。人还是那个人。

回到正题。


写的项目也不少了,但回想起来,实际工作中并没有用过 process.nextTick() 方法(不排除第三方库会用到)。好奇的我于是从网上查了查到底何时要用它,下面是我找到的 2 个相对满意的答案:

1EventEmiter 子类的构造方法中使用

比如,当我们需要在 EventEmiter 实例化后立即发送一个事件(比如 init),代码可以这样写:

class MyEmitter extends EventEmitter {
    constructor() {
        super();
        // 实例化之后立即发送 init 事件
        process.nextTick(() => {
            this.emit('init');
        });
    }
}

// 使用
const myEmitter = new MyEmitter();

myEmitter.once('init', () => {
    console.log('init done!');
});

如果不使用 process.nextTick() 而是直接在构造器中调用 this.emit(),后面的 once() 调用并不能捕获到构造器中的 init 事件,因为在实例构造过程中,once 监听器还没来得及注册。

有疑问的童鞋可以试运行下面的代码:

class MyEmitter extends EventEmitter {
    constructor() {
        super();
        // 实例化之后立即发送 init 事件
        this.emit('init');
    }
}

// 使用
const myEmitter = new MyEmitter();

// 在注册该监听器之前,上面的 emit 就已经发送完成了
// 所以监听不到构造器方法中产生的事件
myEmitter.once('init', () => {
    console.log('init done!');
});

2保持函数的异步性

一个好的实践是,一个方法要么是同步的,要么是异步的,混用常常会产生意想不到的效果。

比如下面这个方法:

function maybeSync(arg, cb{
    if (arg) {
        // 同步调用
        cb();
        return;
    }

    // 异步调用
    fs.stat('file', cb);
}

该方法既可能是同步的也可能是异步的(取决于参数 arg 的值),当使用时:

const maybeTrue = Math.random() > 0.5;

maybeSync(maybeTrue, () => {
  foo();
});

bar();

你无法判断 foo()bar() 谁先执行,让代码难以推理(reason about)。

一个解决办法是,通过 process.nextTick()maybeSync() 完全变成异步的:

function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }

  fs.stat('file', cb);
}

这样一来,我们可以肯定地说,bar() 是先于 foo() 执行的。

3另一个疑问

有童鞋可能要问 process.nextTick() 到底什么时候执行?

简单点,可以这么说:当所有同步方法执行完后,最先被执行的就是 process.nextTick() 里的回调方法。基于此点,process.nextTick() 还有一个坑(gotcha):如果你递归调用 process.nextTick() ,eventloop 就再也没机会执行其它的方法了。


原文始发于微信公众号(背井):process.nextTick()的两个用途

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246663.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!