背景: 后端开发, 对 es6 和 vue 有一定了解, 最近正在折腾研究其原理.
问题概述: 在 async 函数中多执行了一个 nextTick, 导致代码执行时机发生变化
问题详细描述
点击 btn 触发 onClick, onClick 内部先调用 doSomeThing, 然后执行一个 nextTick1, doSomeThing 为 async 函数, 里面 await 了一个 callback(注意 cb 是普通箭头函数), 里面也有一个 nextTick2.
- 若 nextTick2 执行, 'doSomeThing -- close' 会在 nextTick1 回调('onClick $nextTick done')之后执行
- 若 nextTick2 不执行, 'doSomeThing -- close' 会在 nextTick1 回调('onClick $nextTick done')之前执行
问题代码预览: https://codepen.io/zymoplastic/pen/XWdrPpj
截取代码如下
<template>
<button @click="onClick(true)">多执行一个 nextTick</button>
<button @click="onClick(false)">少执行一个 nextTick</button>
</template>
{
data() {
return {}
},
methods: {
async doSomeThing(hasOneMoreTick) {
let cb = () => {
console.log('doSomeThing -- cb');
if (hasOneMoreTick) {
this.$nextTick(() => {
console.log('cb $nextTick done');
})
}
}
await cb();
console.log('doSomeThing -- close');
console.log('call destroy');
},
onClick(hasOneMoreTick) {
console.log(`------hasOneMoreTick: ${hasOneMoreTick} begin ------`);
this.doSomeThing(hasOneMoreTick);
this.$nextTick(() => {
console.log('onClick $nextTick done');
console.log('call destroy');
})
}
}
}
疑问:
- 这个问题去掉 await 就好了, 但是据我查资料了解, await 后面跟一个函数执行(没有返回 Promise 以及没有 then 属性), 应该是直接返回值, 语义上不应该对执行顺序产生影响
- 看 Vue 代码发现 nextTick 内部优先使用 Promise 处理, 多调一次只是把 callback 放到了回调队列里面, 等待引擎的主线程执行完后, 在引擎的任务队列里统一处理所有的回调队列, 那为什么多了一个 callback 会对代码执行的顺序有联系?