Created
August 4, 2022 23:11
-
-
Save odbol/6b832f82d37c86f41f622ebfbf77756c to your computer and use it in GitHub Desktop.
PendingRequest: a way to implement Promise-based APIs across process boundaries like iframes or ServiceWorkers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Deferred} from './Deferred.js'; // See https://gist.github.com/odbol/1a98cf6186caaace78cae9e7a249c992 | |
/** | |
* A PendingRequest. | |
*/ | |
export interface PendingRequest<T> { | |
/** | |
* Id of the request for resolving/rejecting later. | |
*/ | |
requestId: number; | |
/** | |
* The Promise that will be resolved/rejected later. | |
*/ | |
promise: Promise<T>; | |
} | |
/** | |
* Keeps track of Promises that are assigned to requestIds, so you can resolve/reject the Promise later according to its | |
* requestId. | |
* | |
* This is useful for providing Promise-based APIs for things that cannot be tracked within a single Promise's callback, | |
* e.g. when message passing between frames or ServiceWorkers. | |
*/ | |
export class PendingRequests<T> { | |
private curRequestId = 0; | |
private pendingPromises: { [requestId: number]: Deferred<T> } = {}; | |
/** | |
* Create a new PendingRequest. | |
*/ | |
createRequest(): PendingRequest<T> { | |
const requestId = this.curRequestId++; | |
this.pendingPromises[requestId] = new Deferred(); | |
return { | |
requestId, | |
promise: this.pendingPromises[requestId].promise | |
} | |
} | |
/** | |
* Resolve an earlier PendingRequest's promise. | |
* | |
* Returns false if the requestId cannot be found or was already resolved. | |
*/ | |
resolveRequest(requestId: number, result: T): boolean { | |
const deferred = this.pendingPromises[requestId]; | |
if (!deferred) { | |
console.error(`Invalid request ${requestId}`); | |
return false; | |
} | |
deferred.resolve(result); | |
delete this.pendingPromises[requestId]; | |
return true; | |
} | |
/** | |
* Reject an earlier PendingRequest's promise. | |
* | |
* Returns false if the requestId cannot be found or was already resolved. | |
*/ | |
rejectRequest(requestId: number, error: Error): boolean { | |
const deferred = this.pendingPromises[requestId]; | |
if (!deferred) { | |
console.error(`Invalid request ${requestId}`); | |
return false; | |
} | |
deferred.reject(error); | |
delete this.pendingPromises[requestId]; | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment