@midwayjs/event-bus
Version:
Midway event bus
335 lines (242 loc) • 5.74 kB
Markdown
# Event-Bus
Event Bus 用来完成父子进程之间的消息传递,包括同步的调用,异步的发送,以及广播的能力,支持进程、线程、同一进程内调用三种模式。
## Usage
基础使用,在不同的进程间引入。
如下,创建 Thread 模式的 EventBus。
```ts
/**
* in main
*/
import { ThreadEventBus } from '@midwayjs/event-bus';
// 创建一个 bus
const bus = new ThreadEventBus({
isWorker: false,
});
// 添加一个 worker
const worker = new Worker();
bus.addWorker(worker);
// 等待连接和启动
await bus.start();
// 发布消息
bus.publish('hello world');
/**
* in worker
*/
import { ThreadEventBus } from '@midwayjs/event-bus';
// 创建 bus 客户端
const bus = new ThreadEventBus({
isWorker: true,
});
// 启动客户端,自动向 master 发送消息
await bus.start();
// 订阅消息
bus.subscribe(message => {
console.log(message.body);
// => 'hello world'
});
```
可以创建 Cluster 模式的 EventBus,接口相同。
```ts
import { ChildProcessEventBus } from '@midwayjs/event-bus';
// in main
const bus = new ChildProcessEventBus({
isWorker: false,
});
await bus.start();
// in worker
const bus = new ChildProcessEventBus({
isWorker: true,
});
// 启动客户端,自动向 master 发送消息
await bus.start();
```
为了方便同进程研发,也提供了相同接口的 LocalEventBus。
```ts
import { LocalEventBus } from '@midwayjs/event-bus';
// in main
const bus = new LocalEventBus({
isWorker: false,
});
await bus.start();
// in worker
const bus = new LocalEventBus({
isWorker: true,
});
await bus.start();
```
注意,本地模式下,需要在不同文件中,且 worker 只能有一个。
## API
**start**
bus 启动后,需要调用此方法,才能正常使用。
main 调用后会等待 worker 启动,worker 调用后会向 main 发送消息。
```ts
// in main & worker
await bus.start();
```
如果 worker 启动错误,可以传递异常给 main。
```ts
// worker
await bus.start(new Error('worker error'));
// main
bus.onError(error => {
console.log(error.message);
// => 'worker error'
});
```
**Publish & Subscribe**
异步的发送和监听消息,支持 main 和 worker 双向发送, API 一致。
```ts
bus.subscribe(message => {
// message.body === {data: 'abc'}
});
bus.publish({
data: 'abc'
});
```
指定某个 topic 发送消息。
```ts
bus.subscribe(message => {
// message.body === {data: 'abc'}
}, {
topic: 'test'
});
bus.publish({
data: 'abc'
}, {
topic: 'test'
});
```
publish 错误。
```ts
const err = new Error('test');
bus.publish(err);
```
**publishAsync**
同步的发送消息,会等待订阅方返回,包含超时参数,默认 5s。支持 main <-> worker 双向异步通信。
从 main 发送到 worker:
```ts
// in worker
bus.subscribe((message, responder) => {
// message.body === {data: 'abc'}
responder?.send({
data: 'hello world',
});
// send error
responder.error(new Error('test'));
});
// in main
const result = await bus.publishAsync({
data: 'abc'
}, {
timeout: 5000,
});
// result => {data: 'hello world'}
```
从 worker 发送到 main:
```ts
// in main
bus.subscribe((message, responder) => {
// message.body === {data: 'abc'}
responder?.send({
data: 'hello world',
});
});
// in worker
const result = await bus.publishAsync({
data: 'abc'
}, {
timeout: 5000,
});
// result => {data: 'hello world'}
```
使用 try/catch 捕获错误:
```ts
try {
await bus.publishAsync({
data: 'abc'
});
} catch (err) {
// err.message => 'test'
}
```
**publishChunk**
发送消息,会等待订阅方返回多次,包含超时参数,默认 5s。
此 API 仅限于 main 向 worker 发送消息。
`publishChunk` 方法返回的是一个异步迭代器。
```ts
// subscribe
bus.subscribe((message, responder) => {
responder.send('hello');
responder.send(' world');
responder.end();
});
// invoke
const iterator = bus.publishChunk({
data: 'abc'
}, {
timeout: 5000,
});
let result = '';
for await (const data of iterator) {
result += data;
}
```
使用 try/catch 捕获错误。
```ts
const iterator = bus.publishChunk({
data: 'abc'
});
try {
let result = '';
for await (const data of iterator) {
result += data;
}
} catch (err) {
// err.message => 'test'
}
```
**broadcast**
广播消息(一对多)。
```ts
// worker
bus.subscribe(message => {
// message.body === {data: 'abc'}
});
// main
bus.broadcast({
data: 'abc'
});
```
也支持 worker 向其他 main 或者 worker 广播。
```ts
// worker
bus.broadcast('hello world');
```
默认情况下,worker 广播之后,**main** 和 **当前 worker** 都不会收到这条消息
可以通过设置属性,让当前 Worker 也同时接收这条消息。
```ts
// worker
bus.broadcast('hello world', {
includeSelfFromWorker: true,
});
```
可以通过设置属性,让 main 也同时接收这条消息。
```ts
// worker
bus.broadcast('hello world', {
includeMainFromWorker: true,
});
```
## Message 类型
包含以下属性
- `messageId` 用来确定消息的唯一 id
- `workerId` 消息发送的 worker id
- `type` 消息发送的类型,包括 inited(初始化),request(main 向 worker 发送),response(worker 向 main 发送),invoke(同步的 main 向 worker 发送),broadcast(广播)几种类型
- `error` 意外的报错信息
- `messageOptions` 在发送消息时额外的参数,比如超时时间等,具体看类型定义
## 调试
使用环境变量 `NODE_DEBUG=midway:event-bus*` 开启调试输出。
## 注意
所有的消息必须可序列化,不能传递复杂对象,类,方法等。
## License
MIT