Skip to main content
Glama
readablepromise.ts3.31 kB
// SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors // SPDX-License-Identifier: Apache-2.0 /** * The ReadablePromise class wraps a request promise suitable for React Suspense. * See: https://blog.logrocket.com/react-suspense-data-fetching/#wrappromise-js * See: https://github.com/ovieokeh/suspense-data-fetching/blob/master/lib/api/wrapPromise.js */ export class ReadablePromise<T> implements Promise<T> { readonly [Symbol.toStringTag]: string = 'ReadablePromise'; private readonly suspender: Promise<T>; private status: 'pending' | 'error' | 'success' = 'pending'; private response: T | undefined; private error: Error | undefined; constructor(requestPromise: Promise<T>) { this.suspender = requestPromise.then( (res: T) => { this.status = 'success'; this.response = res; return res; }, (err: any) => { this.status = 'error'; this.error = err; throw err; } ); } /** * Returns true if the promise is pending. * @returns True if the Promise is pending. */ isPending(): boolean { return this.status === 'pending'; } /** * Returns true if the promise resolved successfully. * @returns True if the Promise resolved successfully. */ isOk(): boolean { return this.status === 'success'; } /** * Attempts to read the value of the promise. * If the promise is pending, this method will throw a promise. * If the promise rejected, this method will throw the rejection reason. * If the promise resolved, this method will return the resolved value. * @returns The resolved value of the Promise. */ read(): T { switch (this.status) { case 'pending': throw this.suspender; case 'error': throw this.error; default: return this.response as T; } } /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled - The callback to execute when the Promise is resolved. * @param onrejected - The callback to execute when the Promise is rejected. * @returns A Promise for the completion of which ever callback is executed. */ then<TResult1 = T, TResult2 = never>( onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null ): Promise<TResult1 | TResult2> { return this.suspender.then(onfulfilled, onrejected); } /** * Attaches a callback for only the rejection of the Promise. * @param onrejected - The callback to execute when the Promise is rejected. * @returns A Promise for the completion of the callback. */ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult> { return this.suspender.catch(onrejected); } /** * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The * resolved value cannot be modified from the callback. * @param onfinally - The callback to execute when the Promise is settled (fulfilled or rejected). * @returns A Promise for the completion of the callback. */ finally(onfinally?: (() => void) | null): Promise<T> { return this.suspender.finally(onfinally); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/medplum/medplum'

If you have feedback or need assistance with the MCP directory API, please join our Discord server