nextTick().then()用法和相关约束解析

1,856 阅读1分钟

背景

最近发现有个项目中对$nextTick的用法做了约束,统一使用this.$nextTick().then()的方式,此约束来自eslint-plugin-vuevue/next-tick-style

规则详情

此规则强制规定Vue.nextTickthis.$nextTick需要使用callback或者Promise(Vue2.1.0以下推荐)的风格。

  • promise
<script>
import { nextTick as nt } from 'vue';

export default {
  async mounted() {
    /* ✓ GOOD */
    nt().then(() => callback());
    await nt(); callback();
    Vue.nextTick().then(() => callback());
    await Vue.nextTick(); callback();
    this.$nextTick().then(() => callback());
    await this.$nextTick(); callback();

    /* ✗ BAD */
    nt(() => callback());
    nt(callback);
    Vue.nextTick(() => callback());
    Vue.nextTick(callback);
    this.$nextTick(() => callback());
    this.$nextTick(callback);
  }
}
</script>
  • callback
<script>
import { nextTick as nt } from 'vue';

export default {
  async mounted() {
    /* ✓ GOOD */
    nt(() => callback());
    nt(callback);
    Vue.nextTick(() => callback());
    Vue.nextTick(callback);
    this.$nextTick(() => callback());
    this.$nextTick(callback);

    /* ✗ BAD */
    nt().then(() => callback());
    await nt(); callback();
    Vue.nextTick().then(() => callback());
    await Vue.nextTick(); callback();
    this.$nextTick().then(() => callback());
    await this.$nextTick(); callback();
  }
}
</script>

规则配置

默认值为promiseVue版本低于2.1.0才推荐使用callback

{
  "vue/next-tick-style": ["error", "promise" | "callback"]
}

规则分析

尝试去分析为什么引入这项规则

1. 首先是去分析源码

// 只贴出部分代码
export function nextTick (cb?: Function, ctx?: Object) {
  let _resolve
  callbacks.push(() => {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  if (!pending) {
    pending = true
    timerFunc()
  }
  // $flow-disable-line
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}

分析:

  • 可以看到promise的方式其实就是不传callback,然后返回了一个Promise实例,等到timeFunc()生成的异步任务执行resolve
  • 个人观点:其实timerFunc本身就按promiseMutationObserversetImmediatesetTimeout的顺序注册了异步任务,然后promise的格式执行then的时候又是一个异步任务,感觉不是很有必要这样去约束

分析到这里,还是不太理解,然后继续,就到eslint-plugin-vuegithub上去找相关信息

2. 上github查找

然后在上面找到了vue/next-tick-style的提案详情 image.png 总的来说就只是为了代码更加简洁和统一,并没有什么深层次的原因

个人观点:

  • 感觉callback的方式反而更加地直观和简洁,promise的方式还需要在then里面去做回调操作(也可能是用习惯了callback的方式)

综上

建议是爱用哪个用哪个,统一就好

引用

  1. vue/next-tick-style官方文档说明
  2. vue/next-tick-style提案详情