MWSE/sdk/EventPool.js

50 lines
1.8 KiB
JavaScript

// EventPool: pending-request registry and signal fan-out.
//
// Two distinct paths (see issue #33 for why the split matters):
// request() — sends a packet AND registers a waiter for the correlated reply.
// Use ONLY for handlers that return a reply (my/socketid, joinroom, …).
// only() — sends a packet with NO registered waiter (fire-and-forget / WOM).
// Use for pack/to, pack/room without handshake, etc. — anything the
// engine answers nil to, so there is no reply to wait for.
// Confusing the two leaves orphaned Promises or swallowed replies (#33).
export default class EventPool {
constructor(mwse) {
this.wsts = mwse;
this.events = new Map(); // id → [resolve, reject]
this.signals = new Map(); // signalName → [callback, …]
this.count = 0;
}
// request: sends msg and returns a Promise resolved by the server's reply.
request(msg) {
return new Promise((ok, rej) => {
const id = ++this.count;
this.events.set(id, [ok, rej]);
this.wsts.WSTSProtocol.SendRequest(msg, id);
});
}
// only: sends msg without registering a waiter (WOM / fire-and-forget).
only(msg) {
this.wsts.WSTSProtocol.SendOnly(msg);
}
// stream: sends msg and calls callback for every 'C'ontinue reply.
stream(msg, callback) {
const id = ++this.count;
this.wsts.WSTSProtocol.StartStream(msg, id);
this.events.set(id, [callback, () => {}]);
}
// signal: registers a listener for a named server-initiated signal.
signal(event, callback) {
const existing = this.signals.get(event);
if (existing) {
existing.push(callback);
} else {
this.signals.set(event, [callback]);
}
}
}