UNPKG

@thi.ng/rstream

Version:

Reactive streams & subscription primitives for constructing dataflow graphs / pipelines

49 lines (48 loc) 1.65 kB
import { assocObj } from "@thi.ng/transducers/assoc-obj"; import { comp } from "@thi.ng/transducers/comp"; import { map } from "@thi.ng/transducers/map"; import { mapcat } from "@thi.ng/transducers/mapcat"; import { range } from "@thi.ng/transducers/range"; import { transduce } from "@thi.ng/transducers/transduce"; import { sync } from "./sync.js"; import { tunnel } from "./tunnel.js"; const forkJoin = (opts) => { const numWorkers = opts.numWorkers || navigator.hardwareConcurrency || 4; const workerIDs = range(numWorkers); return sync({ src: transduce( map((id) => [ String(id), opts.src.transform(map((x) => opts.fork(id, numWorkers, x))).subscribe( tunnel({ src: opts.worker, transferables: opts.transferables, interrupt: opts.interrupt === true, terminate: opts.terminate, id: String(id) }) ) ]), assocObj(), workerIDs ), xform: comp( // form result tuple in original order map((results) => [...map((id) => results[id], workerIDs)]), // apply user join function map(opts.join) ), reset: true, backPressure: opts.backPressure }); }; const forkBuffer = (minChunkSize = 1) => (id, numWorkers, buf) => { const chunkSize = Math.max(minChunkSize, buf.length / numWorkers | 0); return id < numWorkers - 1 ? buf.slice(id * chunkSize, (id + 1) * chunkSize) : buf.slice(id * chunkSize); }; const joinBuffer = (fn) => fn ? (parts) => [...mapcat(fn, parts)] : (parts) => Array.prototype.concat.apply([], parts); export { forkBuffer, forkJoin, joinBuffer };