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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章