手写观察者模式+手写promise.all

98 阅读1分钟

手写观察者模式

首先观察者模式又叫发布订阅模式或者消息模式,是设计模式中非常著名也非常重要的的一种模式,这种模式一般会定义一个主体和众多的个体,可以订阅不同的消息,当未来消息中心发布某条消息的时候,订阅的个体就会得到通知

代码实现如下:

    let msgCenter = (function(){
      let _msg = {} //存储消息
      /* 
        let _msg = {
          'carInfo': [person1.alreadyRegister.carInfo,person2.alreadyRegister.carInfo,person3.alreadyRegister.carInfo,],
          'newInfo': [person1.alreadyRegister.carInfo,person2.alreadyRegister.carInfo,person3.alreadyRegister.carInfo,]
        }
      */
      return {
        // 用于订阅消息
        reqister: function(type, fn){
          if(_msg[type]){
            _msg[type].push(fn)
          }else{
            _msg[type] = [fn]
          }
        },
        // 用于发布消息
        fire: function(type, args){
          if(!_msg[type]){
            return;
          }else{
            let event = {
              type: type,
              args: args || {}
            }
            for(let i = 0; i < _msg[type].length; i++){
              _msg[type][i](event)
            }
          }
        },
        // 用于取消订阅的消息
        cancel: function(type, fn){
          if(!_msg[type]){
            return;
          }else{
            for(let i = 0; i < _msg[type].length; i++){
              if(_msg[type][i] === fn){
                _msg[type].splice(i, 1)
                break;
              }
            }
          }
        }
      }
    })()

    function Person(){
      this.alreadyRegister = {}
    }
    Person.prototype.reqister = function(type, fn){
      if(this.alreadyRegister[type]){
        console.log('你已经订阅过这个消息了,请不要重复订阅');
      }else{
        msgCenter.reqister(type, fn)
        this.alreadyRegister[type] = fn;
      }
    }
    Person.prototype.cancel = function(type){
      msgCenter.cancel(type, this.alreadyRegister[type])
      delete this.alreadyRegister[type]
    }
    let person1 = new Person()
    let person2 = new Person()
    let person3 = new Person()

    person1.reqister('carInfo', function(e){
      console.log('Person1得到了关于 ' + e.type + ' 的消息, 消息内容:'+ e.args.info);
    })

    person1.reqister('newsInfo', function(e){
      console.log('Person1得到了关于 ' + e.type + ' 的消息, 消息内容:'+ e.args.info);
    })

    person2.reqister('carInfo', function(e){
      console.log('Person2得到了关于 ' + e.type + ' 的消息, 消息内容:'+ e.args.info);
    })

    person3.reqister('newsInfo', function(e){
      console.log('Person3得到了关于 ' + e.type + ' 的消息, 消息内容:'+ e.args.info);
    })

    person3.reqister('carInfo', function(e){
      console.log('Person3得到了关于 ' + e.type + ' 的消息, 消息内容:'+ e.args.info);
    })

    msgCenter.fire('carInfo', {info: '新款汽车上市了!'})
    msgCenter.fire('newsInfo', {info: '某国家领导人访华!'})

    person1.reqister('carInfo', function(e){
      console.log('xxx');
    })

    console.log('------');
    person1.cancel('carInfo')
    msgCenter.fire('carInfo', {info: '再发一条'})

手写promise.all

首先promise.all的使用是,接收一个数组,里面存在的promise,最终按顺序返回promise结果(数组),不处理失败或成功

    let p1 = new Promise((resolve, reject)=>{
      setTimeout(() => {
        resolve(11111)
        // reject(1111)
      }, 3000);
    })
    let p2 = new Promise((resolve, reject)=>{
      setTimeout(() => {
        resolve(22222)
      }, 2000);
    })
    Promise.all([p1, p2]).then(res=>{
      console.log('res',res);
      // res (2) [11111, 22222]
    })
    
    function myPromiseAll(promiseArr){
      return new Promise((resolve, reject)=>{
        let resArr = [promiseArr.length]
        let num = 0
        promiseArr.forEach((item,idx)=>{
          item.then(res=>{
            // resArr.push(res)
            // 不使用push,为了防止结果顺序跟传入顺序不一致
            resArr[idx] = res
            num++
            if(num === promiseArr.length){
              resolve(resArr)
            }
          })
        })
      })
    }
    myPromiseAll([p1,p2]).then(res=>{
      console.log('res',res);
    })