UNPKG

1.9 kBJavaScriptView Raw
1import { AsyncIterableX } from './asynciterablex';
2import { wrapWithAbort } from './operators/withabort';
3import { throwIfAborted } from '../aborterror';
4function wrapPromiseWithIndex(promise, index) {
5 return promise.then((value) => ({ value, index }));
6}
7export class RaceAsyncIterable extends AsyncIterableX {
8 constructor(sources) {
9 super();
10 this._sources = sources;
11 }
12 async *[Symbol.asyncIterator](signal) {
13 throwIfAborted(signal);
14 const sources = this._sources;
15 const length = sources.length;
16 const iterators = new Array(length);
17 const nexts = new Array(length);
18 for (let i = 0; i < length; i++) {
19 const iterator = wrapWithAbort(sources[i], signal)[Symbol.asyncIterator]();
20 iterators[i] = iterator;
21 nexts[i] = wrapPromiseWithIndex(iterator.next(), i);
22 }
23 const next = Promise.race(nexts);
24 const { value: next$, index } = await next;
25 if (!next$.done) {
26 yield next$.value;
27 }
28 const iterator$ = iterators[index];
29 // Cancel/finish other iterators
30 for (let i = 0; i < length; i++) {
31 if (i === index) {
32 continue;
33 }
34 const otherIterator = iterators[i];
35 if (otherIterator.return) {
36 otherIterator.return();
37 }
38 }
39 let nextItem;
40 while (!(nextItem = await iterator$.next()).done) {
41 yield nextItem.value;
42 }
43 }
44}
45/**
46 * Propagates the async sequence that reacts first.
47 *
48 * @export
49 * @param {...AsyncIterable<T>[]} sources The source sequences.
50 * @return {AsyncIterable<T>} An async sequence that surfaces either of the given sequences, whichever reacted first.
51 */
52export function race(...sources) {
53 return new RaceAsyncIterable(sources);
54}
55
56//# sourceMappingURL=race.mjs.map