zoukankan      html  css  js  c++  java
  • 发布-订阅模式

    发布—订阅模式,它定义了一种一对多的依赖关系,当发布者发出一种消息时,所有订阅该消息的任务(回调函数)都将开始执行。
    订阅是希望在某消息或事件发生时可以执行对应的任务;发布指对外广播告知消息已经到达,所有订阅了该消息的任务可以执行了。
    在传统的发布-订阅模式中,如Java,通常需要把订阅者对象自身当成引用传入发布者对象中,而在 JavaScript 中,使用回调函数的形式来代替订阅者。
    nodejs中的on/emit也是采用这种模式在模块间通信的。
    优点:在异步编程中代替传递回调函数;模块间的通信变成松耦合。
      // 发布者对象
      var Pubsub = function () {
        // Storage for topics that can be broadcast or listened to
        this.topics = {};
        // A topic identifier
        this.subUid = -1;
      }
      Pubsub.prototype = {
        // Subscribe to events of interest with a specific topic name and a callback function, to be executed
        // when the topic/event is observed
        subscribe: function (topic, func) {
          if (!this.topics[topic]) {
            this.topics[topic] = [];
          }
          var token = ( ++this.subUid ).toString();
          this.topics[topic].push({
            token: token,
            func: func
          });
          return token;
        },
        // Publish or broadcast events of interest with a specific topic name and arguments
        publish: function (topic, args) {
          if (!this.topics[topic]) {
            return false;
          }
          var subscribers = this.topics[topic];
          subscribers.forEach(function (el) {
            el.func(topic, args)
          });
          return this;
        },
        // Unsubscribe from a specific topic, based on a tokenized reference to the subscription
        unsubscribe: function (token) {
          for (var m in this.topics) {
            if (this.topics[m]) {
              this.topics[m] = this.topics[m].filter(function (el) {
                return el.token !== token;
              });
              return token;
            }
          }
          return this;
        }
      }

    使用:

    //  消息/时间发发生时,执行所有订阅该消息的任务
     var store = new Pubsub();
      store.subscribe('available', function (data) {
        console.log('有货了');
      });
      store.subscribe('available', function (data) {
        console.log('有货了');
      });
      setTimeout(() => store.publish('available',20), 2000)

    解耦模块,方便扩展:

      $.ajax('http:www.example.com/login', function (data) {
        header.setAvatar(data.avatar);
        message.refresh();  // 刷新消息
        cart.refresh();     // 刷新购物车
        address.refresh();   // 新增刷新地址时耦合性太强,不好维护
      });
    
      // 更改为发布-订阅模式:
      //登录模块只需要发布登录成功的消息,不用了解业务方的内部实现及目的。而业务方接受到消息之后,就会开始进行各自的业务处理。
      var login = new Pubsub();
      var header = (function () {   // header 模块
        login.subscribe('loginSuccess', function (data) {
          header.setAvatar(data.avatar);
        });
        return {
          setAvatar: function (data) {
            console.log('设置头像');
          }
        }
      })();
      $.ajax('http:www.example.com/login', function (data) {
        login.publish('loginSuccess', data);   // 发布登录成功的消息
      });
    View Code
  • 相关阅读:
    HDU 3848 CC On The Tree 树形DP
    编程求取直线一般式表达式,两直线交点
    向外国学者所要论文源代码--英语模版
    找出该树中第二小的值--思路及算法实现
    不使用额外空间交换2个数据的源代码
    华为2018软件岗笔试题解题思路和源代码分享
    华为笔试题--LISP括号匹配 解析及源码实现
    Linux 快捷键汇总(偏基础)
    快速排序算法思路分析和C++源代码(递归和非递归)
    Python读取SQLite文件数据
  • 原文地址:https://www.cnblogs.com/kevin2chen/p/7588901.html
Copyright © 2011-2022 走看看