资讯专栏INFORMATION COLUMN

前端异步解决方案-2(发布/订阅模式);

chuyao / 698人阅读

摘要:什么是发布订阅模式什么是发布订阅模式我这里不多就不多阐述了,给大家提供几个我觉得讲的比较好的博文,请各位自行阅读发布订阅模式解释这一篇文章应该是一个写的,但是设计模式这种东西并不分语言,各位可以借鉴一下中理解发布订阅模式这一篇是我们前

什么是发布订阅模式

什么是发布订阅模式我这里不多就不多阐述了,给大家提供几个我觉得讲的比较好的博文,请各位自行阅读
发布-订阅模式解释 这一篇文章应该是一个java coder写的,但是设计模式这种东西并不分语言,各位可以借鉴一下
Javascript中理解发布--订阅模式这一篇是我们前端人写的,但是比较长,大家有耐心可以看看

发布中心实现

我对发布中心的实现,可以不看(看了能够更好的理解发布订阅模式)

//实现发布中心
/*
* log=[{
*   index: Number,                日志编号(自增)
*   type: String,                 日志类型("subscribe","unsubscribe","publish")
*   eventName: String,            事件名
*   time: new Date(),             时间
*   fun:Function                 订阅/取订的方法(只有日志类型为"subscribe"或"unsubscribe"的才有)
*   param:Object                 触发事件时的参数(只有日志类型为"publish"的才有)
* }]
* eventCenter = {
*   eventName:[Function,Function]  //eventName即为事件名,其值为订阅方法列表
* }
* .subscribe(eventName, fun)        订阅  eventName:事件名 fun:订阅方法
* .unsubscribe(eventName, fun)      取订  eventName:事件名 fun:订阅方法
* .publish(eventName[,param])       发布  eventName:事件名 param:事件参数
* .showLog([filter])                日志展示 filter 过滤器,同数组的过滤器用法 返回过滤后的log
* .showEventCenter([eventName])     事件中心 eventName 事件名 返回事件绑定的方法
* */
let subscribeCenter = function () {
  //事件中心
  let eventCenter = {};
  //日志
  let log = [];

  //添加日志函数
  function pushLog(type, eventName, fun, param) {
    let info = {
      index: log.length,
      type: type,
      eventName: eventName,
      time: new Date()
    };
    if (fun) {
      info.fun = fun;
    }
    if (param) {
      info.param = param;
    }
    log.push(info)
  }

  return {
    //订阅
    subscribe(eventName, fun) {
      pushLog("subscribe", eventName, fun);
      eventCenter[eventName] = eventCenter[eventName] || [];
      eventCenter[eventName].push(fun);
    },
    //取消订阅
    unsubscribe(eventName, fun) {
      pushLog("unsubscribe", eventName, fun);
      let onList = eventCenter[eventName];
      if (onList) {
        for (let i = 0; i < onList.length; i++) {
          if (onList[i] === fun) {
            onList.splice(i, 1);
            return
          }
        }
      }
    },
    //发布
    publish(eventName, param) {
      pushLog("publish", eventName, null, param)
      let onList = eventCenter[eventName];
      if (onList) {
        for (let i = 0; i < onList.length; i++) {
          onList[i](param)
        }
      }
    },
    //显示日志
    showLog(filter) {
      filter = filter || (() => true);
      let returnLog = log.filter(filter);
      returnLog.forEach(x => {
        let y = {};
        for (let key in x) {
          y[key] = x[key]
        }
        return y
      });
      return returnLog;
    },
    //显示事件中心
    showEventCenter(eventName) {
      let selectEM = eventName ? eventCenter[eventName] : eventCenter, returnEM = {};
      for (let key in selectEM) {
        returnEM[key] = [];
        selectEM[key].forEach(x => {
          returnEM[key].push(x)
        });
      }
      return returnEM
    }
  }
}();

如果有看我上一篇文章中事件监听实现的朋友应该对这个不部分代码有一种熟悉的感觉,确实事件监听和发布订阅的实现非常的像。我主要多做的就是一个日志的拓展,保证了每次的动作都可以被监听和查看;

发布中心API

这个在上面是有的,但是因为上面的部分有一些同学是不看的,所以就在这里摘出来,方便这些同学了解发布中心的用法

/*
* log=[{
*   index: Number,                日志编号(自增)
*   type: String,                 日志类型("subscribe","unsubscribe","publish")
*   eventName: String,            事件名
*   time: new Date(),             时间
*   fun:Function                 订阅/取订的方法(只有日志类型为"subscribe"或"unsubscribe"的才有)
*   param:Object                 触发事件时的参数(只有日志类型为"publish"的才有)
* }]
* eventCenter = {
*   eventName:[Function,Function]  //eventName即为事件名,其值为订阅方法列表
* }
* .subscribe(eventName, fun)        订阅  eventName:事件名 fun:订阅方法
* .unsubscribe(eventName, fun)      取订  eventName:事件名 fun:订阅方法
* .publish(eventName[,param])       发布  eventName:事件名 param:事件参数
* .showLog([filter])                日志展示 filter 过滤器,同数组的过滤器用法 返回过滤后的log
* .showEventCenter([eventName])     事件中心 eventName 事件名 返回事件绑定的方法
* */
发布/订阅模式在异步中的应用

这里是重点,需要大家仔细看,理解了这段代码不光可以解决异步问题,还可以理解发布订阅者模式是如何应用的;

//发布者
let f1 = function () {
  setTimeout(function () {
    console.log(""done" 事件发布 参数:", 123);
    subscribeCenter.publish("done", 123);
    console.log("事件中心", subscribeCenter.showEventCenter());
    console.log("f3 取订 "done"");
    subscribeCenter.unsubscribe("done", f3);
    setTimeout(function () {
      console.log(""done" 事件发布 参数:", 233);
      subscribeCenter.publish("done", 233);
      console.log("事件中心", subscribeCenter.showEventCenter());
      console.log("日志", subscribeCenter.showLog());
    }, 100)
  }, 100)
};
//订阅者
let f2 = function (param) {
  console.log("f2 is running, param is", param);
};
//订阅者
let f3 = function (param) {
  console.log("f3 is running, param is", param)
};

//订阅
console.log("f2 订阅 "done"");
subscribeCenter.subscribe("done", f2);
console.log("f3 订阅 "done"");
subscribeCenter.subscribe("done", f3);
//发布
f1();

先贴运行结果

在这里可以看到,该模式与事件监听模式非常相似,但是所有的发布都通过了同一个发布中心来控制,这样的话可以方便我们追踪整个事件的状态;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103268.html

相关文章

  • 简单理解观察者模式(pub/sub)在前端中的应用

    摘要:概念观察者模式被广泛地应用于客户端编程中。所有的浏览器事件,等都是使用观察者模式的例子。在观察者模式中,一个对象订阅另一个对象的指定活动并得到通知,而不是调用另一个对象的方法。此外,观察者模式还可用于实现数据绑定。 概念 观察者模式被广泛地应用于JavaScript客户端编程中。所有的浏览器事件(mouseover,keypress等)都是使用观察者模式的例子。这种模式的另一个名字叫自...

    guyan0319 评论0 收藏0
  • [译]为什么前端初学者必须要明白发布订阅模式

    摘要:应用需要正确并合适响应各种网络请求用户操作计时事件和各种延时动作。好了,我们的新流程图画出来了提示城市名称查找不是很复杂,谷歌地图为此提供了非常简单的。形象点表示就是,函数是一等公民。 By Hubert Zub | Oct 3, 2018 原文 当你将关注点从样式,美学和网格系统转移到逻辑,框架和编写JavaScript代码时。一切都开始了,你会发现你处于你的web开发历程中最激动人...

    miqt 评论0 收藏0
  • 微内核架构在大型前端系统中的应用

    摘要:微内核架构在大型前端系统中的应用只讨论架构,不讨论框架名词解释由一群尽可能将数量最小化的软件程序组成,他们负责提供实现一个操作系统所需要的各种机制和功能。而微内核架构已经在操作系统和很多的产品的后端服务及前端中经过了很多的实践。 微内核架构在大型前端系统中的应用 只讨论架构,不讨论框架 1、名词解释 由一群尽可能将数量最小化的软件程序组成,他们负责提供、实现一个操作系统所需要的各种机制...

    li21 评论0 收藏0
  • 小程序的一些小知识总结

    摘要:小程序很多方法都是异步的原因官方说法天生异步刚接触小程序的时候,发现很多微信提供的都是异步的,如路由跳转,设置和读取缓存,还有获取节点信息等微信的,都是异步的,需要传入回调函数才能获得结果,在我们正常的前端开发中,这些都不是异步的,当时很奇 1. 小程序很多方法都是异步的原因(官方说法:天生异步) 刚接触小程序的时候,发现很多微信提供的api都是异步的,如路由跳转,设置和读取缓存,还有...

    阿罗 评论0 收藏0

发表评论

0条评论

chuyao

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<