| 73 | } |
| 74 | |
| 75 | async fireAsync(data: IWaitUntilData<T>, token: CancellationToken): Promise<void> { |
| 76 | if (!this._listeners) { |
| 77 | return; |
| 78 | } |
| 79 | |
| 80 | if (!this._asyncDeliveryQueue) { |
| 81 | this._asyncDeliveryQueue = []; |
| 82 | } |
| 83 | |
| 84 | for (const listener of this._listeners) { |
| 85 | this._asyncDeliveryQueue!.push([listener, data]); |
| 86 | } |
| 87 | |
| 88 | while (this._asyncDeliveryQueue.length > 0 && !token.isCancellationRequested) { |
| 89 | const [listener, data] = this._asyncDeliveryQueue.shift()!; |
| 90 | const thenables: Promise<unknown>[] = []; |
| 91 | |
| 92 | const event = <T>{ |
| 93 | ...data, |
| 94 | token, |
| 95 | waitUntil: (p: Promise<unknown>): void => { |
| 96 | if (Object.isFrozen(thenables)) { |
| 97 | throw new Error('waitUntil can NOT be called asynchronous'); |
| 98 | } |
| 99 | thenables.push(p); |
| 100 | } |
| 101 | }; |
| 102 | |
| 103 | try { |
| 104 | listener(event); |
| 105 | } catch (e) { |
| 106 | console.error(e); |
| 107 | continue; |
| 108 | } |
| 109 | |
| 110 | // freeze thenables-collection to enforce sync-calls to |
| 111 | // wait until and then wait for all thenables to resolve |
| 112 | Object.freeze(thenables); |
| 113 | |
| 114 | await Promise.allSettled(thenables).then((values) => { |
| 115 | for (const value of values) { |
| 116 | if (value.status === 'rejected') { |
| 117 | console.error(value.reason); |
| 118 | } |
| 119 | } |
| 120 | }); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | dispose(): void { |
| 125 | this._listeners.clear(); |