UNPKG

@solana/promises

Version:

Helpers for using JavaScript promises

1 lines 8.77 kB
{"version":3,"sources":["../src/race.ts","../src/abortable.ts"],"names":[],"mappings":"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","file":"index.node.mjs","sourcesContent":["/**\n * Forked from https://github.com/digitalloggers/race-as-promised/tree/master\n *\n * Authored by Brian Kim:\n * https://github.com/nodejs/node/issues/17469#issuecomment-685216777\n *\n * Adapted to module structure.\n *\n * This is free and unencumbered software released into the public domain.\n *\n * Anyone is free to copy, modify, publish, use, compile, sell, or\n * distribute this software, either in source code form or as a compiled\n * binary, for any purpose, commercial or non-commercial, and by any\n * means.\n *\n * In jurisdictions that recognize copyright laws, the author or authors\n * of this software dedicate any and all copyright interest in the\n * software to the public domain. We make this dedication for the benefit\n * of the public at large and to the detriment of our heirs and\n * successors. We intend this dedication to be an overt act of\n * relinquishment in perpetuity of all present and future rights to this\n * software under copyright law.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n *\n * For more information, please refer to <http://unlicense.org/>\n */\n\ntype Deferred = Readonly<{\n reject: (reason?: unknown) => void;\n resolve: (value: unknown) => void;\n}>;\n\nfunction isObject(value: unknown): value is object {\n return value !== null && (typeof value === 'object' || typeof value === 'function');\n}\n\nfunction addRaceContender(contender: object) {\n const deferreds = new Set<Deferred>();\n const record = { deferreds, settled: false };\n\n // This call to `then` happens once for the lifetime of the value.\n Promise.resolve(contender).then(\n value => {\n for (const { resolve } of deferreds) {\n resolve(value);\n }\n\n deferreds.clear();\n record.settled = true;\n },\n err => {\n for (const { reject } of deferreds) {\n reject(err);\n }\n\n deferreds.clear();\n record.settled = true;\n },\n );\n return record;\n}\n\n// Keys are the values passed to race, values are a record of data containing a\n// set of deferreds and whether the value has settled.\nconst wm = new WeakMap<object, { deferreds: Set<Deferred>; settled: boolean }>();\n/**\n * An implementation of [`Promise.race`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/race)\n * that causes all of the losing promises to settle. This allows them to be released and garbage\n * collected, preventing memory leaks.\n *\n * Read more here: https://github.com/nodejs/node/issues/17469\n */\nexport async function safeRace<T extends readonly unknown[] | []>(contenders: T): Promise<Awaited<T[number]>> {\n let deferred: Deferred;\n const result = new Promise((resolve, reject) => {\n deferred = { reject, resolve };\n for (const contender of contenders) {\n if (!isObject(contender)) {\n // If the contender is a primitive, attempting to use it as a key in the\n // weakmap would throw an error. Luckily, it is safe to call\n // `Promise.resolve(contender).then` on a primitive value multiple times\n // because the promise fulfills immediately.\n Promise.resolve(contender).then(resolve, reject);\n continue;\n }\n\n let record = wm.get(contender);\n if (record === undefined) {\n record = addRaceContender(contender);\n record.deferreds.add(deferred);\n wm.set(contender, record);\n } else if (record.settled) {\n // If the value has settled, it is safe to call\n // `Promise.resolve(contender).then` on it.\n Promise.resolve(contender).then(resolve, reject);\n } else {\n record.deferreds.add(deferred);\n }\n }\n });\n\n // The finally callback executes when any value settles, preventing any of\n // the unresolved values from retaining a reference to the resolved value.\n return await (result.finally(() => {\n for (const contender of contenders) {\n if (isObject(contender)) {\n const record = wm.get(contender)!;\n record.deferreds.delete(deferred);\n }\n }\n }) as Promise<Awaited<T[number]>>);\n}\n","import { safeRace } from './race';\n\n/**\n * Returns a new promise that will reject if the abort signal fires before the original promise\n * settles. Resolves or rejects with the value of the original promise otherwise.\n *\n * @example\n * ```ts\n * const result = await getAbortablePromise(\n * // Resolves or rejects when `fetch` settles.\n * fetch('https://example.com/json').then(r => r.json()),\n * // ...unless it takes longer than 5 seconds, after which the `AbortSignal` is triggered.\n * AbortSignal.timeout(5000),\n * );\n * ```\n */\nexport function getAbortablePromise<T>(promise: Promise<T>, abortSignal?: AbortSignal): Promise<T> {\n if (!abortSignal) {\n return promise;\n } else {\n return safeRace([\n // This promise only ever rejects if the signal is aborted. Otherwise it idles forever.\n // It's important that this come before the input promise; in the event of an abort, we\n // want to throw even if the input promise's result is ready\n new Promise<never>((_, reject) => {\n if (abortSignal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(abortSignal.reason);\n } else {\n abortSignal.addEventListener('abort', function () {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(this.reason);\n });\n }\n }),\n promise,\n ]);\n }\n}\n"]}