UNPKG

@solana/promises

Version:

Helpers for using JavaScript promises

1 lines 8.87 kB
{"version":3,"sources":["../src/race.ts","../src/abortable.ts"],"names":[],"mappings":"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","file":"index.browser.cjs","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"]}