Skip to content

Instantly share code, notes, and snippets.

@odbol
Created August 4, 2022 23:11
Show Gist options
  • Save odbol/6b832f82d37c86f41f622ebfbf77756c to your computer and use it in GitHub Desktop.
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.
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