2020-11-04 22:49:01 +00:00
|
|
|
import { logger } from "@coder/logger"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Event emitter callback. Called with the emitted value and a promise that
|
|
|
|
* resolves when all emitters have finished.
|
|
|
|
*/
|
|
|
|
export type Callback<T, R = void | Promise<void>> = (t: T, p: Promise<void>) => R
|
2020-08-09 03:18:49 +00:00
|
|
|
|
2020-02-04 19:27:46 +00:00
|
|
|
export interface Disposable {
|
|
|
|
dispose(): void
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Event<T> {
|
2020-08-09 03:18:49 +00:00
|
|
|
(listener: Callback<T>): Disposable
|
2020-02-04 19:27:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emitter typecasts for a single event type.
|
|
|
|
*/
|
|
|
|
export class Emitter<T> {
|
2020-08-09 03:18:49 +00:00
|
|
|
private listeners: Array<Callback<T>> = []
|
2020-02-04 19:27:46 +00:00
|
|
|
|
|
|
|
public get event(): Event<T> {
|
2020-08-09 03:18:49 +00:00
|
|
|
return (cb: Callback<T>): Disposable => {
|
2020-02-04 19:27:46 +00:00
|
|
|
this.listeners.push(cb)
|
|
|
|
|
|
|
|
return {
|
|
|
|
dispose: (): void => {
|
|
|
|
const i = this.listeners.indexOf(cb)
|
|
|
|
if (i !== -1) {
|
|
|
|
this.listeners.splice(i, 1)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Emit an event with a value.
|
|
|
|
*/
|
2020-11-04 22:49:01 +00:00
|
|
|
public async emit(value: T): Promise<void> {
|
|
|
|
let resolve: () => void
|
|
|
|
const promise = new Promise<void>((r) => (resolve = r))
|
|
|
|
|
|
|
|
await Promise.all(
|
|
|
|
this.listeners.map(async (cb) => {
|
|
|
|
try {
|
|
|
|
await cb(value, promise)
|
|
|
|
} catch (error) {
|
|
|
|
logger.error(error.message)
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
|
|
|
|
resolve!()
|
2020-02-04 19:27:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public dispose(): void {
|
|
|
|
this.listeners = []
|
|
|
|
}
|
|
|
|
}
|