MCPcopy Create free account
hub / github.com/nodejs/node / merge

Function merge

lib/internal/streams/iter/consumers.js:395–514  ·  view source on GitHub ↗

* Merge multiple async iterables by yielding values in temporal order. * @param {...(AsyncIterable |object)} args * @returns {AsyncIterable }

(...args)

Source from the content-addressed store, hash-verified

393 * @returns {AsyncIterable<Uint8Array[]>}
394 */
395function merge(...args) {
396 let sources;
397 let options;
398
399 if (args.length > 0 && isMergeOptions(args[args.length - 1])) {
400 options = args[args.length - 1];
401 sources = ArrayPrototypeSlice(args, 0, -1);
402 } else {
403 sources = args;
404 }
405
406 if (options?.signal !== undefined) {
407 validateAbortSignal(options.signal, 'options.signal');
408 }
409
410 // Normalize each source via from()
411 const normalized = ArrayPrototypeMap(sources, (source) => from(source));
412
413 return {
414 __proto__: null,
415 async *[SymbolAsyncIterator]() {
416 const signal = options?.signal;
417
418 signal?.throwIfAborted();
419
420 if (normalized.length === 0) return;
421
422 if (normalized.length === 1) {
423 for await (const batch of normalized[0]) {
424 signal?.throwIfAborted();
425 yield batch;
426 }
427 return;
428 }
429
430 // Multiple sources - use a ready queue so that batches that settle
431 // between consumer pulls are drained synchronously without an extra
432 // async tick per batch. Each source has at most one pending .next()
433 // at a time. Every batch from every source is preserved.
434 const ready = [];
435 let activeCount = normalized.length;
436 let waitResolve = null;
437
438 // Called when a source's .next() settles. Pushes the result into
439 // the ready queue and wakes the consumer if it's waiting.
440 const onSettled = (iterator, result) => {
441 if (result.done) {
442 activeCount--;
443 } else {
444 ArrayPrototypePush(ready, result.value);
445 // Immediately request the next value from this source
446 // (at most one pending .next() per source)
447 PromisePrototypeThen(
448 iterator.next(),
449 (r) => onSettled(iterator, r),
450 (err) => {
451 ArrayPrototypePush(ready, { __proto__: null, error: err });
452 if (waitResolve) {

Callers

nothing calls this directly

Calls 3

isMergeOptionsFunction · 0.85
validateAbortSignalFunction · 0.85
fromFunction · 0.70

Tested by

no test coverage detected