1.2.0 • Published 2 years ago

@yaohaixiao/subscribers.js v1.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

subscribers.js

npm version Github file size prettier code style Coverage npm downloads MIT License

subscribers.js - 小巧且实用的 JavaScript 发布/订阅工具库。

项目初衷

编写 subscribers.js 主要是在日常的 JavaScript 开发中经常需要使用到发布/订阅模式。所以自己也整理了一个。虽然简单,但基本的功能都有了,还是挺好用的。这个项目的 API 文档就使用到了 subscribers.js。

Features

  • 原生 JavaScript 编写,无任何依赖;
  • 基于 topic 主题的消息,且支持命名空间的订阅/发布;
  • 支持异/同步 发布消息;
  • 支持 UMD 规范,同时也提供 ES6 模块调用;
  • API 接口易于理解和调用简单;

Browsers support

IE / EdgeFirefoxChromeSafariOpera
IE11, Edgelast 10 versionslast 10 versionslast 10 versionslast 10 versions

安装说明

subscribers.js 支持 UMD 规范和 ES6 的模块调用方式,可以在 Node.js 环境中(仅适用于单线程的 Node.js 应用)使用 npm 安装,也可以在浏览器中使用 script 标签引入到页面。

npm 安装

# install from npmjs.com
npm i -S @yaohaixiao/subscribers.js

浏览器中调用

在浏览器中调用 subscribers.js,可以选择调用 jsdelivr 提供的 CDN 服务中的文件,也可以使用本地的 subscribers.js 文件。

CDN 调用 JS 文件

<script src="https://cdn.jsdelivr.net/gh/yaohaixiao/subscribers.js/subscribers.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/yaohaixiao/subscribers.js/subscribers.core.min.js"></script>

本地调用 JS 文件

<script src="/path/to/subscribers.min.js"></script>
<script src="/path/to/subscribers.core.min.js"></script>

Node.js 中调用

const subscribers = require('@yaohaixiao/subscribers.js')

ES6 模块中调用

// 调用完整功能的 subscribers 对象
import subscribers from '@yaohaixiao/subscribers.js/subscribers'

// 调用 Core 版本的 subscribers 对象,仅包含以下方法:
// on()
// emit()
// off()
import subscribers from '@yaohaixiao/subscribers.js/subscribers.core'

Usage

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const Person = {
    name: 'robert',
    age: 24
}

// 创建订阅主题的函数
const handler = (msg, data) => {
    console.log( msg, data )
}

/* ==== 订阅主题 ==== */
// 将函数添加到特定主题的订阅者列表中
subscribers.on('log', handler)
// 设置 handler 的执行上下文为 Person
subscribers.on('log', handler, Person)
// 采用命名空间式的消息主题
subscribers.on('log.info', handler)
subscribers.on('log.info.update', handler)

/* ==== 发布主题 ==== */
// 发布一个(名为:log)消息,log 会触发
subscribers.emit('log', 'hello world!')
// log/log.info/log.info.update 主题的处理器函数都将执行
subscribers.emit('log.info.update', `hello world! it's update!`)

/* ==== 取消订阅 ==== */
// 将 handler 函数从 log 主题中订阅者列表中移除
subscribers.off('log', handler)

const token = Subscribers.on('alert', handler)

// 将 handler 函数从 alert 主题中订阅者列表中移除
subscribers.off('alert', token)

// 移除 log 主题及订阅者列表
subscribers.off('log')

API 文档

subscribers.js 中封装了一系列常用方法,并且适用起来非常方便。

on(topic, handler)

订阅主题,并给出处理器函数。

Parameters

topic

Type: String

Default:

(必须)主题名称。

handler

Type: Function

Default:

(必须)主题的处理器函数。

Returns

Type: String

唯一的 token 字符串,例如:'guid-1'。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = () => {
  console.log('author is Robert')
}

const Person = {
  name: 'robert',
  age: 24
}

subscribers.on('author', handler)
// 设置 handler 的执行上下文为 Person
subscribers.on('log', handler, Person)

// 支持命名空间形式的主题的订阅
subscribers.on('author.career', handler)
subscribers.on('author.career.years', handler)

// 发布消息
subscribers.emit('author', 'Yaohaixiao') // -> `Author: Yaohaixiao`
subscribers.emit('author.career', 'Programmer') // -> `Author: Programmer`
subscribers.emit('author.career.years', 23) // -> `Author: 23`

once(topic, handler)

once() 方法用于订阅主题,并给出处理器函数,仅执行一次。

Parameters

topic

Type: String

Default:

(必须)主题名称。

handler

Type: Function

Default:

(必须)主题的处理器函数。

Returns

Type: String

唯一的 token 字符串,例如:'guid-1'。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = () => {
  console.log('author is Robert')
}

subscribers.once('author', handler)

// 发布消息
subscribers.emit('author')

// 再次发布 handler 将不再执行
subscribers.emit('author')

all(handler)

all() 方法用于订阅所有主题消息发布,任何消息发布都会执行 handler() 处理器。

Parameters

handler

Type: Function

Default:

(必须)处理器函数。

Returns

Type: String

唯一的 token 字符串,例如:'guid-1'。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log(`handler:${msg}`)
}

const callback = (msg) => {
  console.log(`handler:${msg}`)
}

subscribers.on('author', handler)
subscribers.on('career', handler)

// 监听所有消息
subscribers.all(callback)

// 发布消息
subscribers.emit('author', 'Robert')
// -> 'handler:Robert'
// 每次都会触发 all() 方法的订阅处理方法
// -> 'callback:Robert'
subscribers.emit('career', 'Programmer')
// -> 'handler:Programmer'
// -> 'callback:Programmer'

emit(topic, data, async = true)

emit() 用于发布订阅主题信息。

subscribers.js 参考了(PubSubJS)默认是采用异步方式发布的。以确保在消费者处理主题时,主题的发起者不会被阻止。 当然 emit() 方法也支持同步方式(浏览器环境下比较适合)发布主题。

Parameters

topic

Type: String

Default:

(必须)主题名称。

data

Type: Object

Default:

(必须)消息传递的数据对象。

async

Type: Boolean

Default: true

(可选) 是否异步发布。默认值:true。

  • 当 async 设置为 true(默认) 时,异步发布;
  • 当 async 设置为 false 时,同步发布;

Returns

Type: subscribers

subscribers 对象,以便实现链式调用。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log(msg)
}

subscribers.on('author', handler)
subscribers.on('career', handler)
subscribers.on('years', handler)

// 异步发布
subscribers.emit('author', 'ok') // -> 'ok'

// 同步发布
// 延迟10毫秒:应该看输出 ok 后输出 programmer
subscribers.emit('career', 'programmer', false) // -> 'programmer'

notify(topic, data)

notify() 用于同步发布订阅主题信息,是 emit() 方法的别名。

Parameters

topic

Type: String

Default:

(必须)主题名称。

data

Type: Object

Default:

必须)消息传递的数据对象。

Returns

Type: subscribers

subscribers 对象,以便实现链式调用。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log(msg)
}

subscribers.on('author', handler)
subscribers.on('career', handler)
subscribers.on('years', handler)

// 依次输出:'author'、'career'、'years'
subscribers.notify('author', 'ok') // -> 'ok'
subscribers.notify('career', 'programmer') // -> 'programmer'
subscribers.notify('years', 19) // -> 19

off(topic, token)

off() 方法用来取消订阅主题。

Parameters

topic

Type: String

Default:

(必须)主题名称。

token

Type: Function|String

Default:

(可选)订阅主题的处理器函数或者唯一 Id 值。

Returns

Type: subscribers

subscribers 对象,以便实现链式调用。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log('handler:', msg)
}

const callback = (msg) => {
  console.log('callback:', msg)
}

subscribers.on('author', handler)

const token = subscribers.on('career', handler)
const guid = subscribers.on('career', handler)

// 取消订阅 author 主题
subscribers.off('author', handler)

// 删除订阅 career 主题下的 handler 处理器
subscribers.off('career', token)

// 删除订阅 career 主题下的 callback 处理器
subscribers.off('career', guid)

// 订阅 career 主题下2个处理器都删除后
// 会取消整个 author 主题订阅,因此再发布 author 主题消息
// 不会有任何反应
subscribers.emit('career', 'web developer')

get(topic)

get() 方法用来获取全部或者包含 topic 主题或者订阅 token 的订阅者信息。

Parameters

topic

Type: String

Default:

(可选)主题名称。

  • 不传递 topic 参数,返回全部订阅者信息;
  • 传递 topic 参数
    • 如果是 topic 主题:返回包含 topic 主题的订阅者信息;
    • 如果是订阅 token:返回包含此 token 信息的 topic 主题的订阅者信息;

Returns

Type: Array | Object

返回全部或者包含 topic 主题或者订阅 token 的订阅者信息。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log('handler:', msg)
}

subscribers.on('author', handler)
subscribers.on('career', handler)
subscribers.on('years', handler)

const token = subscribers.on('years', handler)

// 获取 author 主题订阅者信息
subscribers.get('author')
// -> 返回 author 主题的订阅信息
// [
//   topic: 'author',
//   callback: handler,
//   token: 'guid-1'
// ]

subscribers.get(token)
// -> 返回 career 主题的订阅信息
// [
//   topic: 'career',
//   callback: handler,
//   token: 'guid-2'
// ]

// 获取所有订阅者信息
subscribers.get()
// -> 返回所有主题的订阅信息
// {
//   'author': [
//     topic: 'author',
//     callback: handler,
//     token: 'guid-1'
//   ]
//   'career': [
//     topic: 'career',
//     callback: handler,
//     token: 'guid-2'
//   ]
//   'years': [
//     topic: 'years',
//     callback: handler,
//     token: 'guid-3'
//   ]
// }

has(topic, isDirect = true)

has() 方法用于判断是否存在包含 topic 指定的订阅者信息。

Parameters

topic

Type: String

Default:

(可选)主题名称。

  • 传递 topic 参数:判断指定 topic 或者消息主题的命名空间中包含 topic 的订阅信息;
  • 不传递 topic 参数:判断是否包含任何订阅信息;
isDirect

Type: Boolean

Default: true

(可选)是否完全匹配 topic。

  • true:匹配完全相同的主题或者主题的命名空间中包含 topic 的订阅;
  • false:只匹配与指定 topic 主题完全相同的主题;

Returns

Type: Boolean

  • true:有相关的订阅信息;
  • false:无相关的订阅信息;
import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log('handler:', msg)
}

subscribers.on('author', handler)
subscribers.on('author.career.years', handler)

subscribers.has('author.career')
// => true - 因为包含 author 主题

subscribers.has('author.career.year')
// => true 因为有完全匹配的主题

subscribers.has('author.career', false)
// => false 因为没有完全匹配的主题

subscribers.has()
// => true

remove(topic)

remove() 方法用来删除特定 topic 主题的订阅者信息。

Parameters

topic

Type: String|Array

Default:

(必须)主题名称。

  • String 类型:删除单个 topic 订阅信息;
  • Array 类型:删除多个 topic 订阅信息;

Returns

Type: subscribers

subscribers 对象,以便实现链式调用。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log('handler:', msg)
}

const callback = (msg) => {
  console.log('callback:', msg)
}

subscribers.on('author', handler)
subscribers.on('publish', callback)

// 删除 author 主题相关的所有信息
subscribers.remove('author')

// 同时删除 author 和 publish 主题相关的所有信息
subscribers.remove(['author', 'publish'])

clear()

clear() 方法用于清理所有订阅者(主题和处理器的)信息。

Returns

Type: subscribers

subscribers 对象,以便实现链式调用。

import subscribers from '@yaohaixiao/subscribers.js/subscribers'

const handler = (msg) => {
  console.log('handler:', msg)
}

subscribers.on('author', handler)
subscribers.on('author.career', handler)
subscribers.on('author.career.years', handler)

// 清理所有订阅者(主题和处理器的)信息
subscribers.clear()

subscribers.has() // -> false

License

Licensed under MIT License.

1.2.0

2 years ago

1.1.0

2 years ago

1.0.0

2 years ago

0.5.0

2 years ago

0.4.0

2 years ago

0.3.0

2 years ago

0.2.0

2 years ago