|
1 | 1 | import { StackAssertionError, captureError } from "./errors"; |
| 2 | +import { DependenciesMap } from "./maps"; |
2 | 3 | import { Result } from "./results"; |
3 | 4 | import { generateUuid } from "./uuids"; |
4 | 5 |
|
@@ -38,28 +39,45 @@ export function createPromise<T>(callback: (resolve: Resolve<T>, reject: Reject) |
38 | 39 | } as any); |
39 | 40 | } |
40 | 41 |
|
| 42 | +const resolvedCache = new DependenciesMap<[unknown], ReactPromise<unknown>>(); |
41 | 43 | /** |
42 | | - * Like Promise.resolve(...), but also adds the status and value properties for use with React's `use` hook. |
| 44 | + * Like Promise.resolve(...), but also adds the status and value properties for use with React's `use` hook, and caches |
| 45 | + * the value so that invoking `resolved` twice returns the same promise. |
43 | 46 | */ |
44 | 47 | export function resolved<T>(value: T): ReactPromise<T> { |
45 | | - return Object.assign(Promise.resolve(value), { |
| 48 | + if (resolvedCache.has([value])) { |
| 49 | + return resolvedCache.get([value]) as ReactPromise<T>; |
| 50 | + } |
| 51 | + |
| 52 | + const res = Object.assign(Promise.resolve(value), { |
46 | 53 | status: "fulfilled", |
47 | 54 | value, |
48 | 55 | } as const); |
| 56 | + resolvedCache.set([value], res); |
| 57 | + return res; |
49 | 58 | } |
50 | 59 |
|
| 60 | +const rejectedCache = new DependenciesMap<[unknown], ReactPromise<unknown>>(); |
51 | 61 | /** |
52 | | - * Like Promise.resolve(...), but also adds the status and value properties for use with React's `use` hook. |
| 62 | + * Like Promise.reject(...), but also adds the status and value properties for use with React's `use` hook, and caches |
| 63 | + * the value so that invoking `rejected` twice returns the same promise. |
53 | 64 | */ |
54 | 65 | export function rejected<T>(reason: unknown): ReactPromise<T> { |
55 | | - return Object.assign(Promise.reject(reason), { |
| 66 | + if (rejectedCache.has([reason])) { |
| 67 | + return rejectedCache.get([reason]) as ReactPromise<T>; |
| 68 | + } |
| 69 | + |
| 70 | + const res = Object.assign(Promise.reject(reason), { |
56 | 71 | status: "rejected", |
57 | 72 | reason: reason, |
58 | 73 | } as const); |
| 74 | + rejectedCache.set([reason], res); |
| 75 | + return res; |
59 | 76 | } |
60 | 77 |
|
| 78 | +const neverResolvePromise = pending(new Promise<never>(() => {})); |
61 | 79 | export function neverResolve(): ReactPromise<never> { |
62 | | - return pending(new Promise<never>(() => {})); |
| 80 | + return neverResolvePromise; |
63 | 81 | } |
64 | 82 |
|
65 | 83 | export function pending<T>(promise: Promise<T>, options: { disableErrorWrapping?: boolean } = {}): ReactPromise<T> { |
|
0 commit comments