@soundworks/core
Version:
Open-source creative coding framework for distributed applications based on Web technologies
74 lines (63 loc) • 2.02 kB
JavaScript
import { BATCHED_TRANSPORT_CHANNEL } from './constants.js';
/**
* This class proxies transports given the SharedStateManager to batch messages
*
* @param {number} [options.wait=0] - Wait for given number of milliseconds
* for stacking messages before emitting on the network. If 0 is given, network
* message is emitted on next microtask
* @private
*/
class BatchedTransport {
#transport = null;
#listeners = new Map();
#stack = [];
#sending = false;
constructor(transport) {
this.#transport = transport;
this.#transport.addListener(BATCHED_TRANSPORT_CHANNEL, stack => {
stack.forEach(entry => {
const [channel, args] = entry;
// server side the transport is the same EventEmitter instance
// for both state manager server and client, so channel might not exist
// one side or the other.
if (this.#listeners.has(channel)) {
const callbacks = this.#listeners.get(channel);
callbacks.forEach(callback => callback(...args));
}
});
});
}
addListener(channel, callback) {
if (!this.#listeners.has(channel)) {
this.#listeners.set(channel, new Set());
}
const callbacks = this.#listeners.get(channel);
callbacks.add(callback);
}
async emit(channel, ...args) {
this.#stack.push([channel, args]);
if (!this.#sending) {
this.#sending = true;
await false;
this.#sending = false;
const stack = this.#stack;
this.#stack = [];
this.#transport.emit(BATCHED_TRANSPORT_CHANNEL, stack);
}
}
removeListener(channel, callback) {
if (!this.#listeners.has(channel)) {
const callbacks = this.#listeners.get(channel);
callbacks.delete(callback);
}
}
removeAllListeners(channel = null) {
if (channel === null) {
this.#listeners.clear();
} else if (this.#listeners.has(channel)) {
const callbacks = this.#listeners.get(channel);
callbacks.clear();
}
}
}
export default BatchedTransport;