JS設計模式——等待者模式

等待者模式

作用:通過對多個異步進程對監聽,對未來事件進行統一管理。在es6、7的promise等異步處理方法沒有出現前,常用等待着模式對異步事件進行管理。

function Waiter() {
  // 相當於私有變量,因爲new的時候是不會把這個往實例this裏放的
  var dfd = []  // 存放所有異步狀態
  var doneArr = [] //存放所有成功的回調
  var failArr = [] // 存放所有失敗的回調
  // 註冊所有異步方法
  this.when = function() {
    // 獲取auguments 是一個類數組對象
    // 讓類數組使用數組的方法,成爲真正的數組
    dfd = Array.prototype.slice.call(arguments)
    // 從後往前判斷,因爲要刪除數組元素,刪除元素後遍歷會改變
    for(var i = dfd.length-1; i > 0; i--) {
      var d = dfd[i]
      // 判斷狀態實例是否都符合要求
      if(!d || d.rejected || d.resolved || (d instanceof Defer)) {
        // 剔除不符合的實例
        dfd.splice(i, 1)
      } 
    }
    // 鏈式調用
    return this
  }
  // 成功的回調
  this.done = function() {
    var args = Array.prototype.slice.call(arguments)
    doneArr = doneArr.concat(args)
    return this
  }
  // 失敗回調
  this.fail = function() {
    var args = Array.prototype.slice(arguments)
    failArr = failArr.concat(args)
    return this
  }

  this.Defered = function() {
    // 創建狀態實例
    return new Defer()
  }
  // 定義狀態類
  var Defer = function() {
    // 狀態值
    this.resolved = false
    this.rejected = false
  }
  Defer.prototype = {
    resolve: function() {
      this.resolved = true
      console.log('async resolve')
      for(var i = 0; i < dfd.length; i++) {
        if(!dfd[i].resolved) {
          return
        }
        // 如果全部完成,就不會return出去,則可執行下面的語句
        // 執行成功的回調函數
        _exec(doneArr)
      }
    }, 
    reject: function() {
      console.log('async reject')
      this.rejected = true
      // 執行失敗的回調
      _exec(failArr)
    }
  }
  // 執行回調
  function _exec(arr) {
    console.log('callback')
    for(var i = 0; i < arr.length; i++) {     
      // 存在arr[i],執行
      if(arr[i]) arr[i]()
    }
  }
}
var waiter = new Waiter()
// 創建三個異步對象
var async1 = function() {
  // 創建狀態實例
  var dfd = waiter.Defered()
  setTimeout(function() {
    console.log('async1 done')
    dfd.resolve()
  }, 1000)
  return dfd
}
var async2 = function() {
  var dfd = waiter.Defered()
  setTimeout(function() {
    console.log('async2 done')
    dfd.resolve()
  }, 1000)
  return dfd
}
var async3 = function() {
  var dfd = waiter.Defered()
  setTimeout(function() {
    console.log('async3 done')
    dfd.resolve()
  }, 1000)
  return dfd
}
waiter.when((async1(), async2(), async3())).done(function() {
  console.log('success')
}).fail(function() {
  console.log('fail')
})

上述等待者模式代碼相比其他設計模式略有些複雜,在其中有一些技巧需要注意一下:

  • 在註冊異步實例、判斷是否執行完畢或失敗時用到了鏈模式return this
  • 在類中用內部變量和函數構成私有變量,如dfddoneArrfailArr
  • 定義內部類Defer
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章