Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default Values in Collector #231

Merged
merged 16 commits into from
Dec 20, 2023
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased][unreleased]

- Added `defaults` to `Collector` options

## [5.1.0][] - 2023-12-17

- Support waiting for promise in `Collector.wait`
Expand Down
13 changes: 12 additions & 1 deletion lib/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,40 @@ class Collector {
exact = true;
reassign = true;
timeout = 0;
defaults = {};
#fulfill = null;
#reject = null;
#cause = null;
#controller = null;
#signal = null;
#timeout = null;

constructor(keys, { exact = true, timeout = 0, reassign = false } = {}) {
constructor(keys, options = {}) {
const { exact = true, reassign = false } = options;
const { timeout = 0, defaults = {} } = options;
this.keys = keys;
if (exact === false) this.exact = false;
if (reassign === false) this.reassign = reassign;
if (typeof defaults === 'object') this.defaults = defaults;
this.#controller = new AbortController();
this.#signal = this.#controller.signal;
if (typeof timeout === 'number' && timeout > 0) {
this.#timeout = AbortSignal.timeout(timeout);
this.#signal = AbortSignal.any([this.#signal, this.#timeout]);
this.#timeout.addEventListener('abort', () => {
if (Object.keys(this.defaults).length > 0) this.#default();
if (this.done) return;
this.fail(this.#timeout.reason);
});
}
}

#default() {
for (const [key, value] of Object.entries(this.defaults)) {
if (this.data[key] === undefined) this.set(key, value);
}
}

get signal() {
return this.#controller.signal;
}
Expand Down
2 changes: 2 additions & 0 deletions metautil.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ export function sizeToBytes(size: string): number;

export interface CollectorOptions {
exact?: boolean;
defaults?: object;
timeout?: number;
reassign?: boolean;
}
Expand All @@ -247,6 +248,7 @@ export class Collector {
count: number;
exact: boolean;
timeout: number;
defaults: object;
reassign: boolean;
signal: AbortSignal;
constructor(keys: Array<string>, options?: CollectorOptions);
Expand Down
28 changes: 28 additions & 0 deletions test/collector.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,34 @@ metatests.test('Collector: timeout', async (test) => {
}
});

metatests.test('Collector: default values', async (test) => {
const defaults = { key1: 1 };

const dc1 = collect(['key1'], { defaults, timeout: 50 });
const dc2 = collect(['key1'], { defaults: {}, timeout: 50 });
const dc3 = collect(['key1', 'key2'], { defaults, timeout: 50 });
dc3.set('key2', 1);

setTimeout(() => {
dc1.set('key1', 2);
dc2.set('key1', 2);
dc3.set('key1', 2);
}, 100);

const result1 = await dc1;
test.strictSame(result1, defaults);
const result3 = await dc3;
test.strictSame(result3, { ...defaults, key2: 1 });

try {
await dc2;
test.error(new Error('Should not be executed'));
} catch (error) {
test.strictSame(error.message, 'The operation was aborted due to timeout');
}
test.end();
});

metatests.test('Collector: fail', async (test) => {
const dc = collect(['key1']);

Expand Down
Loading