@mtdt.temp/browser-core
Version:
Datadog browser core utilities.
83 lines • 2.74 kB
JavaScript
import { queueMicrotask } from './queueMicrotask';
// eslint-disable-next-line no-restricted-syntax
export class Observable {
constructor(onFirstSubscribe) {
this.onFirstSubscribe = onFirstSubscribe;
this.observers = [];
}
subscribe(observer) {
this.addObserver(observer);
return {
unsubscribe: () => this.removeObserver(observer),
};
}
notify(data) {
this.observers.forEach((observer) => observer(data));
}
addObserver(observer) {
this.observers.push(observer);
if (this.observers.length === 1 && this.onFirstSubscribe) {
this.onLastUnsubscribe = this.onFirstSubscribe(this) || undefined;
}
}
removeObserver(observer) {
this.observers = this.observers.filter((other) => observer !== other);
if (!this.observers.length && this.onLastUnsubscribe) {
this.onLastUnsubscribe();
}
}
}
export function mergeObservables(...observables) {
return new Observable((globalObservable) => {
const subscriptions = observables.map((observable) => observable.subscribe((data) => globalObservable.notify(data)));
return () => subscriptions.forEach((subscription) => subscription.unsubscribe());
});
}
// eslint-disable-next-line no-restricted-syntax
export class BufferedObservable extends Observable {
constructor(maxBufferSize) {
super();
this.maxBufferSize = maxBufferSize;
this.buffer = [];
}
notify(data) {
this.buffer.push(data);
if (this.buffer.length > this.maxBufferSize) {
this.buffer.shift();
}
super.notify(data);
}
subscribe(observer) {
let closed = false;
const subscription = {
unsubscribe: () => {
closed = true;
this.removeObserver(observer);
},
};
queueMicrotask(() => {
for (const data of this.buffer) {
if (closed) {
return;
}
observer(data);
}
if (!closed) {
this.addObserver(observer);
}
});
return subscription;
}
/**
* Drop buffered data and don't buffer future data. This is to avoid leaking memory when it's not
* needed anymore. This can be seen as a performance optimization, and things will work probably
* even if this method isn't called, but still useful to clarify our intent and lowering our
* memory impact.
*/
unbuffer() {
queueMicrotask(() => {
this.maxBufferSize = this.buffer.length = 0;
});
}
}
//# sourceMappingURL=observable.js.map