Vue2.0中的異步隊列

在vue的體系中惕医,數據的雙向綁定主要通過<code>Object.defineProperty</code>進行數據從模型到視圖的流動及通過DOM事件進行數據從視圖到模型的流動。這些都比較容易理解龙优,但是如果頻繁的更改模型的話,就會造成頻繁的更新View事秀,會造成頻繁的dom操作彤断,這是比較耗時的,因此需要進行優(yōu)化易迹,Vue2.0是通過批處理進行優(yōu)化的宰衙,而異步執(zhí)行隊列,是批處理中一個很重要的一個環(huán)節(jié)睹欲。

在vue.js(Vue.js v2.1.10)416-490行供炼,描述了這一神奇的異步執(zhí)行隊列一屋。下面我們將進行相關的代碼分析。

  • 1.函數整體
var nextTick =(function(){
  return function queueNextTick (cb, ctx) {}
})()

我們可以看到整體來說袋哼,這是一個由立即執(zhí)行函數構成的冀墨,返回值是函數的一個函數,我們可以使用下面的測試代碼

var nextTick =(function(){
return function queueNextTick (cb, ctx) {
  console.log(cb);
}
})();
nextTick("this is test1")
  • 2.函數內容
var nextTick = (function () {
    var callbacks = [];
    var pending = false;
    var timerFunc;

    function nextTickHandler () {
    }
  if (typeof Promise !== 'undefined' && isNative(Promise)) {
    var p = Promise.resolve();
    var logError = function (err) { console.error(err); };
    timerFunc = function () {
      p.then(nextTickHandler).catch(logError);
      if (isIOS) { setTimeout(noop); }
    };
  } else if (typeof MutationObserver !== 'undefined' && (
    isNative(MutationObserver) ||
    MutationObserver.toString() === '[object MutationObserverConstructor]'
  )) {
    var counter = 1;
    var observer = new MutationObserver(nextTickHandler);
    var textNode = document.createTextNode(String(counter));
    observer.observe(textNode, {
      characterData: true
    });
    timerFunc = function () {
  }
  return function queueNextTick (cb, ctx) {
  }
})();

我們看到在函數內部涛贯,有三個函數诽嘉,nextTickHandler,timerFunc弟翘,以及queueNextTick 虫腋。
其中

if(typeof Promise !== 'undefined' && isNative(Promise)){
}
else if(typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'){
}else{
}

是用來判斷當前執(zhí)行環(huán)境,給timerFunc 選擇一個合適的執(zhí)行條件衅胀。如果是支持Promise的環(huán)境中岔乔,timerFunc 中則用<code>p.then(nextTickHandler)</code>和 <code>setTimeout(nextTickHandler, 0);</code>執(zhí)行回調;如果是MutationObserver環(huán)境則通過修改文本節(jié)點的值的變化觸發(fā)調用的的滚躯。關于為什么優(yōu)先使用Promise雏门,知乎里也在討論這件事,點這里看詳情掸掏。

  • 3.函數的返回函數
function queueNextTick (cb, ctx) {
    var _resolve;
    callbacks.push(function () {
      if (cb) { cb.call(ctx); }
      if (_resolve) { 
          console.log(0);
           _resolve(ctx); }
    });
    if (!pending) {
      pending = true;
      timerFunc();
    }
    if (!cb && typeof Promise !== 'undefined') {
      return new Promise(function (resolve) {
          console.log("now")
        _resolve = resolve;
      })
    }
  }

當我們使用<code>nextTick(function Test(){console.log("1" +this.isIOS);},this)</code>時茁影,我們可以發(fā)現 Test封裝后被放進了回調隊列callbacks中,

if (cb) { cb.call(ctx); }
if (_resolve) { 
       console.log(0);
        _resolve(ctx); }

注意這里的_resolve丧凤,他是在

if (!cb && typeof Promise !== 'undefined') {
   return new Promise(function (resolve) {
     _resolve = resolve;
   })
 }

里面進行了賦值募闲,因為promise注冊函數是立即執(zhí)行的,因此在返回前給當前的域中的_resolve賦了值愿待。當進行回調時浩螺,便可以使用_resolve的值。我們可以使用執(zhí)行空函數進行測試:

console.log(nextTick();)//打印是Promise的相關內容 
  • 4.nextTickHandler隊列回調控制函數
function nextTickHandler () {
    pending = false;
    //對callbacks進行深復制
    var copies = callbacks.slice(0);
    callbacks.length = 0;
    for (var i = 0; i < copies.length; i++) {
        if(i==0){
            copies[i]();
        }
      copies[i]();
    }
  }

此函數便是在觸發(fā)時把回調隊列中函數依次調用仍侥,特別注意 pending=flase這句話用來把執(zhí)行回調過程中新加進回調數組的計入下一個tick要出,另外需要注意<code> var copies =callbacks.slice(0); callbacks.length = 0;
</code>這句話,用的很好农渊,首先對回掉數組進行深復制患蹂,然后把callbacks置空余掖。之所以不用callbacks=[]考抄,是因為設置length=0可以不改變原有對象的地址怠蹂。

  • 5.如何實現隊列的功能
    我們使用測試代碼:
nextTick().then(()=>{
  console.log("last");
})
var ss={
    isIOS:"sss"
}
nextTick(function(){
    console.log("1" +this.isIOS);
},ss)

最后我畫出了隊列圖

隊列執(zhí)行圖
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末钧惧,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子羊赵,更是在濱河造成了極大的恐慌漏麦,老刑警劉巖骗灶,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件游添,死亡現場離奇詭異盛末,居然都是意外死亡弹惦,警方通過查閱死者的電腦和手機否淤,發(fā)現死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門悄但,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人石抡,你說我怎么就攤上這事檐嚣。” “怎么了啰扛?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵嚎京,是天一觀的道長。 經常有香客問我隐解,道長鞍帝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任煞茫,我火速辦了婚禮帕涌,結果婚禮上,老公的妹妹穿的比我還像新娘续徽。我一直安慰自己蚓曼,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布钦扭。 她就那樣靜靜地躺著纫版,像睡著了一般。 火紅的嫁衣襯著肌膚如雪客情。 梳的紋絲不亂的頭發(fā)上其弊,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音膀斋,去河邊找鬼梭伐。 笑死,一個胖子當著我的面吹牛概页,可吹牛的內容都是我干的籽御。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼惰匙,長吁一口氣:“原來是場噩夢啊……” “哼技掏!你這毒婦竟也來了?” 一聲冷哼從身側響起项鬼,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤哑梳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后绘盟,有當地人在樹林里發(fā)現了一具尸體鸠真,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡悯仙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了吠卷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锡垄。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖祭隔,靈堂內的尸體忽然破棺而出货岭,到底是詐尸還是另有隱情,我是刑警寧澤疾渴,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布千贯,位于F島的核電站,受9級特大地震影響搞坝,放射性物質發(fā)生泄漏搔谴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一桩撮、第九天 我趴在偏房一處隱蔽的房頂上張望敦第。 院中可真熱鬧,春花似錦距境、人聲如沸申尼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽师幕。三九已至,卻和暖如春诬滩,著一層夾襖步出監(jiān)牢的瞬間霹粥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工疼鸟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留后控,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓空镜,卻偏偏與公主長得像浩淘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吴攒,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內容