Next.js website for Rocky Mountain Vending company featuring: - Product catalog with Stripe integration - Service areas and parts pages - Admin dashboard with Clerk authentication - SEO optimized pages with JSON-LD structured data Co-authored-by: Cursor <cursoragent@cursor.com>
105 lines
No EOL
2.9 KiB
Text
105 lines
No EOL
2.9 KiB
Text
/**
|
|
* @license
|
|
* Copyright 2024 Google Inc.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
import { TimeoutError } from '../common/Errors.js';
|
|
/**
|
|
* Creates and returns a deferred object along with the resolve/reject functions.
|
|
*
|
|
* If the deferred has not been resolved/rejected within the `timeout` period,
|
|
* the deferred gets resolves with a timeout error. `timeout` has to be greater than 0 or
|
|
* it is ignored.
|
|
*
|
|
* @internal
|
|
*/
|
|
export class Deferred {
|
|
static create(opts) {
|
|
return new Deferred(opts);
|
|
}
|
|
static async race(awaitables) {
|
|
const deferredWithTimeout = new Set();
|
|
try {
|
|
const promises = awaitables.map(value => {
|
|
if (value instanceof Deferred) {
|
|
if (value.#timeoutId) {
|
|
deferredWithTimeout.add(value);
|
|
}
|
|
return value.valueOrThrow();
|
|
}
|
|
return value;
|
|
});
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
return await Promise.race(promises);
|
|
}
|
|
finally {
|
|
for (const deferred of deferredWithTimeout) {
|
|
// We need to stop the timeout else
|
|
// Node.JS will keep running the event loop till the
|
|
// timer executes
|
|
deferred.reject(new Error('Timeout cleared'));
|
|
}
|
|
}
|
|
}
|
|
#isResolved = false;
|
|
#isRejected = false;
|
|
#value;
|
|
// SAFETY: This is ensured by #taskPromise.
|
|
#resolve;
|
|
// TODO: Switch to Promise.withResolvers with Node 22
|
|
#taskPromise = new Promise(resolve => {
|
|
this.#resolve = resolve;
|
|
});
|
|
#timeoutId;
|
|
#timeoutError;
|
|
constructor(opts) {
|
|
if (opts && opts.timeout > 0) {
|
|
this.#timeoutError = new TimeoutError(opts.message);
|
|
this.#timeoutId = setTimeout(() => {
|
|
this.reject(this.#timeoutError);
|
|
}, opts.timeout);
|
|
}
|
|
}
|
|
#finish(value) {
|
|
clearTimeout(this.#timeoutId);
|
|
this.#value = value;
|
|
this.#resolve();
|
|
}
|
|
resolve(value) {
|
|
if (this.#isRejected || this.#isResolved) {
|
|
return;
|
|
}
|
|
this.#isResolved = true;
|
|
this.#finish(value);
|
|
}
|
|
reject(error) {
|
|
if (this.#isRejected || this.#isResolved) {
|
|
return;
|
|
}
|
|
this.#isRejected = true;
|
|
this.#finish(error);
|
|
}
|
|
resolved() {
|
|
return this.#isResolved;
|
|
}
|
|
finished() {
|
|
return this.#isResolved || this.#isRejected;
|
|
}
|
|
value() {
|
|
return this.#value;
|
|
}
|
|
#promise;
|
|
valueOrThrow() {
|
|
if (!this.#promise) {
|
|
this.#promise = (async () => {
|
|
await this.#taskPromise;
|
|
if (this.#isRejected) {
|
|
throw this.#value;
|
|
}
|
|
return this.#value;
|
|
})();
|
|
}
|
|
return this.#promise;
|
|
}
|
|
}
|
|
//# sourceMappingURL=Deferred.js.map |