首頁  >  文章  >  web前端  >  jquery.Callbacks的實作詳解

jquery.Callbacks的實作詳解

高洛峰
高洛峰原創
2016-12-03 13:25:52944瀏覽

前言

jQuery.Callbacks是jquery在1.7版本之後加入的,是從1.6版中的_Deferred物件中抽離的,主要用來進行函數佇列的add、remove、fire、lock等操作,並提供once 、memory、unique、stopOnFalse四個option進行一些特殊的控制。

功能介紹

jq的Callbacks模組主要是為其他模組提供服務的,他就像一個溫柔的小女人,在背後默默地付出。 Deferred就像一個巨人,在jq中那麼的突出,但在內部,他受到Callbacks的服務。

Callbacks的幾個狀態:

      once    -- 回呼函數只執行一次

       -- 狀態記憶,主要用於Deferred中

      stopOnFalse -- 遇到return false 終止回呼清單繼續執行

我自己實作的Callbacks的幾個簡單的方法

      add    -- 為對應的回調  依序執行函數

      has    -- 回呼這樣做:

var cb = Callback('memory once') // 得到一个拥有记忆功能并只执行一次的回调模块

   


由於我們需要基於一定狀態來得到不同的實例,我們可以確定,我們需要一個儲存狀態的物件

var callbackState = {}

   

,我們要怎麼記錄這兩個狀態呢,在這裡,仿jq來寫的一個函數來實現,如下:

var createCallbackState = function (options) {
 var states = options.split(' ')
 var obj = {}
 for (var i = 0; i < states.length; i++) {
  obj[states[i]] = true
 }
 return obj
 }

   

以上代碼,將 'memory once'  變成了 {memory: trueonce: true} ,如果狀態快取物件裡有這個對象,直接回傳,沒有的話先創建再返回。

接下來,就是Callback函數的全部程式碼了,先上程式碼

var Callback = function (options) {
 
 var state = callbackState[options] //获取状态模式
 if (!state) {
  callbackState[options] = state = createCallbackState(options)
 }
 var list = [], // 回调函数列表
  memory,  // 存储是否为 记忆状态
  has = function (fn) {
  for (var i = 0; i < list.length; i++) {
   if (list[i] === fn) {
   return true
   }
  }
  return false
  },
  add = function () {
  var i = 0,
   args = arguments,
   len = args.length
  for (; i < len; i++) {
   if (state.unique && has(args[i])) { // 如果是unique状态下并回调列表已经拥有该函数,则不添加
   continue
   }
   list.push(args[i])
  }
  },
  fire = function (context, args) {
  var i = 0,
   len = list.length,
   item
  for (; i < len; i++) {
   item = list[i]
   if (item.apply(context,args) === false && state.stopOnFalse) { //如果函数运行返回false,并且是stopOnFalse状态,终止循环
   break;
   }
  }
  }
 
 return {
  add: function () {
  add.apply(null,arguments)
  // 如果memory模式并且已经拥有了memory信息,接着出发函数
  if (state.memory && memory) {
   fire(memory[0], memory[1])
   list = []
  }
  },
  fire: function (context, args) {
  // 如果memory模式,并且list是空,代表触发在添加前,保存memory信息
  if (state.memory && !list.length) {
   memory = [context, args]
   return
  }
  fire(context,args)
  if (state.once) {
   this.clear()
  }
  },
  has: function (fn) {
  return has(fn)
  },
  clear: function () {
  list = []
  }
 }
 
 }

   

Callback函數執行後,傳回一個對象,然後該物件包含了幾個簡單的功能。

下面我來介紹一下這部分的實作。

首先,如jq一樣,我也定義了內部的add, fire, has方法,主要原因是邏輯需要,在返回對象的方法中實現once,memory狀態控制,內部的add,fire方法是純粹的添加和觸發函數。

先來看cb.add方法,add方法可以接收多個函數,因此

add.apply(null,arguments)

   

使用內部的add做添加功能

下的一部分的功能是這個回調模組是否是這個回調模組狀態,理解Deferred模組的同學應該知道,該模組是Promise模式,訂閱成功或失敗狀態的回調函數,然後再某一時刻觸發他,這個模式便引用了memory狀態下的Callback,這個模式有一個奇怪的地方,如果你先發布成功,但是回呼列表空空如也,那麼程式並不會發布失敗,而是等待成功回呼函數的加入,一但回呼函數加入,立刻執行他。

就是如下程式碼

// 如果memory模式并且已经拥有了memory信息,立刻触发函数
 if (state.memory && memory) {
 fire(memory[0], memory[1])
 list = []
 }

   

提示: '如果你先發佈成功,但是回呼列表空空如也,那麼程式並不會發布失敗,而是等待成功回呼函數的加入,一但回調函數加入,立刻執行他' 的理解如下程式碼

var cb = Callback(&#39;memory&#39;) // 得到记忆功能的回调模块
 
cb.fire() // 触发回调队列
 
cb.add(fn) //添加回调函数,自动执行了!
 
function fn () {
 console.log(&#39;fn&#39;)
}

   

如果在非memory狀態,上述程式碼無效。需要再次fire才會執行。

經過上述,fire函數也好理解了,fire可接收兩個參數,函數上下文,函數參數數組。

與add中memory狀態的程式碼連串起來,以下程式碼是fire時memory狀態下的操作

// 如果memory模式,并且list是空,代表触发在添加前,保存memory信息
  if (state.memory && !list.length) {
   memory = [context, args]
   return
  }

   

如果是memory狀態,回呼列表為空,就保存函數執行上下文和參數數組,等add時立刻執行。

除了上述以外,程式碼就很簡單易懂啦,Callback函數就到這裡了,很簡單的功能,唯一一點不好理解的就是memory狀態。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn