@apollo/client
Version:
A fully-featured caching GraphQL client.
72 lines (71 loc) • 2.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineLatestBatched = combineLatestBatched;
const rxjs_1 = require("rxjs");
/**
* Like `combineLatest` but with some differences:
*
* - It only works on arrays as an input
* - Batches updates to each array index that contains a referentially equal
* observable
* - Doesn't allow for custom scheduler
* - Expects array of constructed observables instead of `Array<ObservableInput>`
*/
function combineLatestBatched(observables) {
if (observables.length === 0) {
return rxjs_1.EMPTY;
}
return new rxjs_1.Observable((observer) => {
const { length } = observables;
// Keeps track of current values for each observable
const values = new Array(length);
// Used to batch an update each item in the array that share an observable
// so that they can be emitted together.
const indexesByObservable = new Map();
observables.forEach((source, idx) => {
if (!indexesByObservable.has(source)) {
indexesByObservable.set(source, new Set());
}
indexesByObservable.get(source).add(idx);
});
// Track the number of active subscriptions so we know when to complete this
// observable
let active = indexesByObservable.size;
// Track how many observables are left to emit their first value
let remainingFirstValues = indexesByObservable.size;
let currentBatch;
// Subscribe to each unique observable instead of the raw source array of
// observables since we want at most 1-subscription per unique observable.
// This ensures an update can write to multiple indexes before emitting the
// result.
indexesByObservable.forEach((indexes, source) => {
let hasFirstValue = false;
const subscription = source.subscribe({
next: (value) => {
indexes.forEach((idx) => (values[idx] = value));
if (!hasFirstValue) {
hasFirstValue = true;
remainingFirstValues--;
}
if (!remainingFirstValues) {
currentBatch ||= new Set(observables.filter((obs) => obs.dirty));
currentBatch.delete(source);
if (!currentBatch.size) {
observer.next(values.slice());
currentBatch = undefined;
}
}
},
complete: () => {
active--;
if (!active) {
observer.complete();
}
},
error: observer.error.bind(observer),
});
observer.add(subscription);
});
});
}
//# sourceMappingURL=combineLatestBatched.cjs.map