短小精悍的发布订阅库 mitt

更新日期: 2023-02-14阅读: 790标签: 

介绍

mitt 是一个小而美的发布-订阅库,短短的几十行代码,小于 200b 的体积,提供三个重要的 api。然而麻雀虽小,五脏俱全。


发布-订阅模式

发布-订阅模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象。这个主题对象在自身状态变化时,会通知所有订阅者对象,使它们能够自动更新自己的状态。


用法

有这样的一个需求,小明想买 100w 以内的二手房,小华想买 150w 左右的二手房,但是房产中介告诉他俩,暂时没有他们想要的房源,中介的工作人员留下他俩的联系方式,一旦有合适的房源就通过电话通知。这就是一个经典使用发布-订阅的模式的场景。请看下面的代码。

const mitt = require("mitt");

const houseAgents = mitt();

houseAgents.on("xiaoming", () => {
  console.log("有 100w 以内的房源了");
});

houseAgents.on("xiaohua", () => {
  console.log("有 150w 左右的房源了");
});

过了一段时间,中介收到 150w 左右的房源,立马通知 xiaohua。

houseAgents.emit("xiaohua");


源码分析

mitt 通过几十行代码实现了发布-订阅机制。我们来剖析一下 mitt 源码。

function mitt(all) {
  all = all || Object.create(null);

  return {
    on: function () {
      /* some code*/
    },
    emit: function () {
      /* some code*/
    },
    off: function () {
      /* some code*/
    },
  };
}

mitt 库的源码中只有一个 mitt 函数。它接收 all 参数,返回一个对象,该对象包含 on、emit、off 三个方法。

all = all || Object.create(null);

mitt 方法接收 all 参数,all 用来存储监听的事件。当传入的 all 的值是 undefined、null、""、false、NaN 等值时,all 的值默认为 Object.create(null), 它是一个没有 __proto__ 属性的对象。

实际上,这里缺少类型处理。比如 mitt(true), 就会导致错误。

const mitt = require("mitt");
const ob = mitt(true);

ob.on("a", () => {});
ob.emit("a", "dd");

建议 all 的类型是对象类型或者不传。推荐传入空对象或数组。

const mitt = require("mitt");
const ob = mitt();
/* 
  or
  const ob = mitt([]);
  const ob = mitt({});

*/

接下来,我们来看看 mitt 里非常重要的三个方法。

// ...
on: function on(type, handler) {
  (all[type] || (all[type] = [])).push(handler);
}

// ...

on 接收两个参数,type 类型和 handler 事件处理方法。方法体内仅有一行非常优雅的代码。当该类型存在时,就将其事件处理追加到数组后面,当该类型不存在时,初始化一个空数组,用来存储该类型的事件处理方法。

emit: function emit(type, evt) {
  (all[type] || []).slice().map(function (handler) {
    handler(evt);
  });
  (all["*"] || []).slice().map(function (handler) {
    handler(type, evt);
  });
}

订阅事件使用 on 方法,发布事件使用 emit 方法。emit 方法里就做了一件事,根据事件类型,将该类型订阅的所有事件遍历调用。


不足

通过分析 mitt 的源码,我们会发现,mitt 没有考虑匿名函数情况,在使用 on 方法时,传入的第二个参数必须是具名函数。


手动实现发布订阅库

class PubSub {
  constructor() {
    this.listeners = [];
  }

  sub(type, handler, always) {
    console.log(this.listeners[type] || []);
    if (!this.listeners[type]) {
      this.listeners[type] = [];
    }
    this.listeners[type].push({ handler, always });
  }

  on(type, handler, always = true) {
    this.sub(type, handler, always);
  }

  once(type, handler, always = false) {
    this.sub(type, handler, always);
  }

  emit(type, evt) {
    if (this.listeners[type]) {
      this.listeners[type].forEach((listener) => {
        listener.handler(evt);
      });

      this.listeners[type] = this.listeners[type].slice().filter((listener) => Boolean(listener.always));
    }
  }

  off(type, handler) {
    if (this.listeners[type]) {
      this.listeners[type] = this.listeners[type]
        .slice()
        .filter((listener) => listener.handler.toString() !== handler.toString());
    }
  }
}

来自:https://segmentfault.com/a/1190000043417806

链接: https://fly63.com/article/detial/12365

JavaScript 社区由一个库引发的“smoosh门”事件到底怎么回事?

一项名为 JavaScript 功能的提案 Array.prototype.flatten 证明与 Web 不兼容。在 Firefox Nightly 中发布该功能会导致至少一个受欢迎的网站中断。鉴于有问题的代码是广泛使用的 MooTools 库的一部分,很可能会有更多网站受到影响。

15个有趣的Javascript 和CSS库

让你了解到新兴和酷炫的web 开发趋势. 精心挑选发布一些认为大家值得关注的库:Direction Reveal、Carbon、Аxios、Jarvis、Toast UI Editor、Micron.js、lit

math.js_灵活强大的JavaScript数学库

math.js是一个广泛应用于JavaScript 和 Node.js的数学库,它的特点是灵活表达式解析器,支持符号计算,内置大量函数与常量,并提供集成解决方案来处理不同的数据类型,如数字,大数字,复数,分数,单位和矩阵。

12 个评估 JS 库你需要关心的事

当你调研一个 JS 库,功能当然是最重要的。作者给出了从 12 个角度全面分析 JS 库的可用性,分别是:特性,稳定性,性能,包生态,社区,学习曲线,文档,工具,发展历史,团队,兼容性,趋势

在使用新的JavaScript库时需要考虑的12件事

对于今年的JavaScript状态调查,我想深入挖掘一下,不仅知道人们正在使用哪些工具和库,还要为什么他们选择使用它们。这意味着我必须找到一种方法将个人偏好转化为冷酷的数据。

React Native 常用的 15 个库

本篇 React native 库列表不是从网上随便找的, 这些是我在我的应用中亲自使用的库。 这些库功能可能跟其它库也有,但经过大量研究并在我的程序中尝试后,我选择了这些库。

10个有趣的javascript和css库

我们的使命是让您了解最新和最酷的Web开发趋势。下面为大家分享10个有趣的javascript和css库:Tessaract.js强大的javascript(节点和浏览器)库,用于从图像中提取文本。

5个功能丰富的交互式Js库

在javascript的帮助下,可以为几乎每个领域(如移动、桌面应用程序和游戏Web开发)创建Web应用程序,因为该编程语言用作服务器端编程语言以实现最大功能,所以它是一种很好的编程语言。在本文中,我们选择了一些最佳的javascript库汇总

Js常用的动态效果库有那些?

当我想要在网上找一个简洁的 Javascript 动效库时,总是发现很多“推荐”的库都是缺乏持续维护的。经过一番研究,我收集了 11 个最好的库,你可以用在自己的项目中。另外我还添加了一些有用但是缺少持续维护的库

10 个实用的 Vue.js 工具和库

如今 Vue 的热度不断攀升,使用者越来越多,Vue.js 工具也随处可见。这种现象不是凭空产生的:Vue 的学习曲线友好,功能驱动的结构清晰易懂,文档出色易学,所以新人入门很容易,经验丰富的开发人员也可以快速从其他框架

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!