nextTick
咱們先把這部分源碼復(fù)制出來
var isUsingMicroTask = false;//nextTick 最終是否以微任務(wù)執(zhí)行,在下面如果瀏覽器支持promise和MutationObserver的話,這個就會改變成true
var callbacks = [];//用來存放nextTick傳進(jìn)來的函數(shù)
var pending = false;
function nextTick(cb, ctx) {
var _resolve;
//callbacks在這里是存放傳進(jìn)來的cb
callbacks.push(function () {
if (cb) {
// 同時會進(jìn)行異常捕獲
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(function (resolve) {
_resolve = resolve;
});
}
}
timerFunc
這里主要使用了Promise.then > MutationObserver > setImmediate > setTimeOut;這四種來實(shí)現(xiàn)異步,然后優(yōu)先級就是這樣
這里主要是在頁面剛引入vue.js的時候,進(jìn)行判斷,看看當(dāng)前環(huán)境是不是支持,咱們可以在這里加上console.log,然后再瀏覽器里面看看
var timerFunc;
// 這里優(yōu)先使用Promise,因?yàn)閜romise的then是微任務(wù),執(zhí)行速度比較快
if (typeof Promise !== 'undefined' && isNative(Promise)) {
console.log('這里使用了Promise')
var p_1 = Promise.resolve();
timerFunc = function () {
p_1.then(flushCallbacks);
if (isIOS)
setTimeout(noop);
};
isUsingMicroTask = true;
}
else if (!isIE &&
typeof MutationObserver !== 'undefined' &&
(isNative(MutationObserver) ||
MutationObserver.toString() === '[object MutationObserverConstructor]')) {
console.log('這里使用了MutationObserver')
var counter_1 = 1;
var observer = new MutationObserver(flushCallbacks);
var textNode_1 = document.createTextNode(String(counter_1));
observer.observe(textNode_1, {
characterData: true
});
timerFunc = function () {
counter_1 = (counter_1 + 1) % 2;
textNode_1.data = String(counter_1);
};
isUsingMicroTask = true;
}
else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
console.log('這里使用了setImmediate')
timerFunc = function () {
setImmediate(flushCallbacks);
};
}
else {
// 這里最后使用setTimeout,
console.log('這里使用了setTimeout')
timerFunc = function () {
setTimeout(flushCallbacks, 0);
};
}
查看打印的結(jié)果,看到當(dāng)前瀏覽器是支持promise

image.png
flushCallbacks
function flushCallbacks() {
pending = false;
// 這里復(fù)制了一份出來,同時清空callbacks
var copies = callbacks.slice(0);
callbacks.length = 0;
// 這里遍歷copies里面的函數(shù),然后按順序執(zhí)行
for (var i = 0; i < copies.length; i++) {
copies[i]();
}
}