Skip to content

Instantly share code, notes, and snippets.

@jaydenseric
Created May 3, 2022 07:46
Show Gist options
  • Select an option

  • Save jaydenseric/2e9db5ab90bd92a3cf0a48f3ce87effa to your computer and use it in GitHub Desktop.

Select an option

Save jaydenseric/2e9db5ab90bd92a3cf0a48f3ce87effa to your computer and use it in GitHub Desktop.
A JavaScript with TypeScript JSDoc solution for a deferred promise that can be externally resolved or rejected.
// @ts-check
/**
* A deferred promise that can be externally resolved or rejected.
* @template [Resolves=void] What the promise resolves.
* @extends {Promise<Resolves>}
*/
export default class Deferred extends Promise {
/** @typedef {(value: Resolves | PromiseLike<Resolves>) => void} Resolve */
/** @typedef {(reason?: any) => void} Reject */
constructor() {
/** @type {Resolve | undefined} */
let _resolve;
/** @type {Reject | undefined} */
let _reject;
super((resolve, reject) => {
_resolve = resolve;
_reject = reject;
});
/** Resolves the promise. */
this.resolve = /** @type {Resolve} */ (_resolve);
/** Rejects the promise. */
this.reject = /** @type {Reject} */ (_reject);
}
static get [Symbol.species]() {
return Promise;
}
get [Symbol.toStringTag]() {
return "Deferred";
}
}
// @ts-check
import Deferred from "./Deferred.mjs";
const deferred = new Deferred();
setTimeout(() => {
deferred.resolve();
}, 1000);
// Has a void type.
const foo = await deferred;
// @ts-check
import Deferred from "./Deferred.mjs";
const deferred = /** @type {Deferred<boolean>} */ (new Deferred());
setTimeout(() => {
deferred.resolve(
// TS only allows a boolean here.
true
);
}, 1000);
// Has a boolean type.
const foo = await deferred;
@jaydenseric
Copy link
Copy Markdown
Author

An alternative approach (where the Deferred class doesn’t extend Promise for less complexity at the cost of slightly worse ergonomics) can be seen at https://gist.github.com/jaydenseric/13923f5ea130ad669f7d35c4aeec70ac .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment