服務內建一個事件匯流器來支援事件驅動架構,以及發送事件至本地與遠端服務。
注意,內建的事件是射後不理的,若服務為離線狀態則事件將會丟失。對於需要持久、耐用及可靠的事件請使用 moleculer-channels 。
事件監聽器是按邏輯群組排列的,因此邏輯群組中僅有一個監聽器會被觸發。
假設你有三個服務
PAYMENT
、BILLING
,每個服務都訂閱到user.purchased
,並且啟動了一個PAYMENT
服務及兩個BILLING
服務。當你發出user.purchased
事件時,將只有一個PAYMENT
服務及一個BILLING
服務實例的事件會被觸發。
Fig. 1. 平衡事件範例
group
名稱預設會是服務名稱,但是它可以在服務的事件中設定覆蓋。
module.exports = {
name: "payment",
events: {
"order.created": {
// 以 "other" 註冊覆蓋預設的 "payment" 群組名稱
group: "other",
handler(ctx) {
console.log("Payload:", ctx.params);
console.log("Sender:", ctx.nodeID);
console.log("Metadata:", ctx.meta);
console.log("The called event name:", ctx.eventName);
}
}
}
}
你可以使用 broker.emit
函數來發送平衡事件。
broker.emit(eventName[, payload[, groups]]);
參數說明:
eventName
<String> 事件名稱payload
<Object> 資料參數groups
<String> | <String[]> 服務名稱範例:
// 限 `mail` 與 `payments` 接收
broker.emit("user.created", { user }, ["mail", "payments"]);
使用 broadcast
可以發送廣播至所有的本地及遠端事件。但它不會進行事件平衡,所有的服務實例都會接收到事件。
Fig. 2. 廣播事件範例
使用 broker.broadcast
函數來發送廣播事件。
broker.broadcast(eventName[, payload[, groups]]);
參數說明:
eventName
<String> 事件名稱payload
<Object> 資料參數groups
<String> | <String[]> 服務名稱範例:
// 所有的 `user` 與 `purchase` 都接收
broker.broadcast("user.created", { user }, ["user", "purchase"]);
使用 broker.broadcastLocal
函數限制僅對本地服務發送廣播事件。
broker.broadcastLocal(eventName[, payload[, groups]]);
從 v0.14 版事件處理開始支援 Context。如果你使用事件驅動架構並想要追蹤事件,那麼事件 Context 會是很有幫助的。事件擁有與 Actions 非常相近的 Context,差別僅在於一些新事件相關屬性。完整清單請參閱:
https://moleculer.services/docs/0.14/context.html
範例:事件處理中的 context 以及發送事件
module.exports = {
name: "accounts",
events: {
"user.created"(ctx) {
console.log("Payload:", ctx.params);
console.log("Sender:", ctx.nodeID);
console.log("Metadata:", ctx.meta);
console.log("The called event name:", ctx.eventName);
ctx.emit("accounts.created", { user: ctx.params.user });
},
"user.removed": {
// 強制使用新版 context
context: true,
handler(ctx) {
console.log(`${this.broker.nodeID}:${this.fullName}: Event '${ctx.eventName}' received. Payload:`, ctx.params, ctx.meta);
}
},
"user.oldCreated": {
context: false,
// 此為 v0.13 版參數格式,建議直接使用新版 v0.14 寫法
handler(payload, sender, event, ctx) {
console.log("Payload:", payload);
console.log("Sender:", sender);
console.log("Metadata:", ctx.meta);
console.log("The called event name:", event);
}
}
}
};
範例:使用萬用字元 (?, *, **) 訂閱事件。
module.exports = {
name: "accounts",
events: {
// 訂閱至所有的 `user` 事件
"user.*"(ctx) {
console.log("User event:", ctx.params);
},
// 訂閱至所有的事件
"**"(ctx) {
console.log(`Event '${ctx.eventName}' received from ${ctx.nodeID} node:`, ctx.params);
}
}
};
事件也支援類似於 Actions 的參數驗證器。就如 Actions 的定義,你應該在事件中定義 params
並使用內建 Validator 來驗證參數。
module.exports = {
name: "mailer",
events: {
"send.mail": {
// 驗證參數
params: {
from: "string|optional",
to: "email",
subject: "string"
},
handler(ctx) {
this.logger.info("Event received, parameters OK!", ctx.params);
}
}
}
};
服務中內建了一些廣播事件。這些事件會以字首為 $ 字號進行命名。
$services.changed
節點載入或銷毀$circuit-breaker.opened
斷路器狀態變更為 open
$circuit-breaker.half-opened
斷路器狀態變更為 half-open
$circuit-breaker.closed
斷路器狀態變更為 closed
$node.connected
節點連線或重新連線$node.updated
節點更新資訊時$node.disconnected
節點斷線$broker.started
服務啟動$broker.stopped
服務停止$transporter.connected
Transporter 連線$transporter.disconnected
Transporter 斷線$broker.error
服務錯誤$transit.error
Transit 錯誤$transporter.error
Transporter 錯誤$cacher.error
Cacher 錯誤$discoverer.error
服務搜尋錯誤由於內建事件繁多,詳情請參閱官方手冊:
https://moleculer.services/docs/0.14/events.html#Internal-events
[1] Events, https://moleculer.services/docs/0.14/events.html
context
是用來將舊版的參數格式強制改為新版,假如你不是由舊版升級上來的使用者,可以直接忽略 context 設定。