2015年12月12日 星期六

jQuery的Callbacks

jQuery有一個對控制異步函式時很好用的類別Deferred,還有它的簡少API版本,Promise(無法更改state)。

我們可以藉由觀看jQuery的源始碼(jquery-1.11.3.js)來較清楚地了解Deferred到底做了什麼事及怎麼實現的,以更好的運用Deferred及其相關API。

在了解Deferred之前,我們可以先來了解Callbacks這個類別。在這邊用形象的方式來了解Callbacks的運作方式。

Callbacks可以被當成是一個佇列式的列隊(先進先出,FIFO),我們可以把想要做的function傳進列隊中(add()),並在想要的時候觸發列隊中的function執行(fire() or fireWith()),在這邊是一次執行所有的function,雖然有照順序開始執行,但並無法保證一個function執行完才執行下一個(例如要花時間的異步函式)。

而Deferred則是利用Callbacks的性質來實作的,基本上就是預先將異步函式做完時要執行的回調函式先放到列隊中,並執行異步函式,等異步函式執行完後手動決定要觸發列隊裡函式並執行的時機。

jQuery的Callbacks有以下常用的API function
  1. $.Callbacks([flags]) : 創建並返回一個Callbacks類別。
    • flags : 可選,可以接受多個,用空格的String來表示,例如有以下幾種:
      •  once:
        • 列隊只能被觸發一次(fire)。
      •  memory:
        • 列隊觸發後,一有函式放進(add)列隊會被馬上執行。
      •  unique:
        • 列隊中的同樣函式(指的是其參考一樣的 reference)再一次觸發時只會被執行一次。
  2. Callbacks.add(callbacks) : 將callbacks函式放進Callbacks列隊中。
  3. Callbacks.fire([arguments]) : 觸發列隊執行其中的函式。
    • arguments : 可選,可傳入參數給列隊中各函式當input value。
  4. Callbacks.fireWith([context] [, arguments]) : 跟fire()相似,也是觸發列隊執行其中的函式,不過可以指定上下文(context),即函式中的this指誰。
  5. Callbacks.disable() : 將callback列隊disable掉,即之後不能在做fire()之類的呼叫(呼叫了也不會有行為)
範例 :


  1. $.Callbacks() :
    function funGenerator(funId){
     return function(){
       console.log(funId);
      }
    }
    
    var callbacks = $.Callbacks();
    callbacks.add(funGenerator('f1'));
    callbacks.add(funGenerator('f2'));
    callbacks.fire();  //output : f1 ,f2
    callbacks.fire();  //output : f1 ,f2
  2. $.Callbacks('once') :
    function funGenerator(funId){
     return function(){
       console.log(funId);
      }
    }
    
    var callbacks = $.Callbacks('once');
    callbacks.add(funGenerator('f1'));
    callbacks.add(funGenerator('f2'));
    callbacks.fire();  //output : f1 ,f2
    callbacks.fire();  //no output
  3. $.Callbacks('memory') :
    function funGenerator(funId){
     return function(){
       console.log(funId);
      }
    }
    
    var callbacks = $.Callbacks('memory');
    callbacks.add(funGenerator('f1'));
    callbacks.add(funGenerator('f2'));
    callbacks.fire();  //output : f1 ,f2
    callbacks.add(funGenerator('f3'));  //output : f3

沒有留言 :

張貼留言