Skip to content

Commit

Permalink
Replace Promise.withResolvers with our own version
Browse files Browse the repository at this point in the history
  • Loading branch information
avillega committed Aug 27, 2024
1 parent 313eca5 commit b2b6c3e
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 4 deletions.
3 changes: 2 additions & 1 deletion lib/core/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Resonate } from "../resonate";
import { ErrorCodes, ResonateError } from "./errors";
import { RetryPolicy, isRetryPolicy } from "./retry";
import { TaskMessage, TasksSource } from "./tasksSource";
import * as utils from "./utils";

export type ResumeBody = {
promiseId: string;
Expand Down Expand Up @@ -121,7 +122,7 @@ export class TasksHandler {
}

localCallback<R>(promiseId: string): Promise<R> {
const { promise, resolve, reject } = Promise.withResolvers();
const { promise, resolve, reject } = utils.promiseWithResolvers();
this.#callbackPromises.set(promiseId, { resolve, reject });
return promise as Promise<R>;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/core/tasksSources/http.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as http from "node:http";
import { Logger } from "../loggers/logger";
import { TasksSource, TaskMessage, isTaskMessage } from "../tasksSource";
import * as utils from "../utils";

const STOP = "stop";

export class HttpTaskSource implements TasksSource {
readonly url: URL;
readonly generator: AsyncGenerator<TaskMessage, void, unknown>;
readonly stopPromise: PromiseWithResolvers<void> = Promise.withResolvers();
readonly stopPromise: utils.PromiseWithResolvers<void> = utils.promiseWithResolvers<void>();

/**
* Constructs a new instance of the HttpTaskSource with the provided URL and an optional logger.
Expand Down
3 changes: 2 additions & 1 deletion lib/core/tasksSources/local.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { TaskMessage, TasksSource } from "../tasksSource";
import * as utils from "../utils";

export class LocalTasksSource implements TasksSource {
private taskQueue: TaskMessage[] = [];
private resolver: ((taskMessage: TaskMessage) => void) | undefined;
private stopPromise: PromiseWithResolvers<void> = Promise.withResolvers();
private stopPromise: utils.PromiseWithResolvers<void> = utils.promiseWithResolvers<void>();
readonly generator: AsyncGenerator<TaskMessage, void, unknown>;

constructor() {
Expand Down
35 changes: 35 additions & 0 deletions lib/core/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,38 @@ export function promiseState(p: Promise<any>): Promise<"pending" | "resolved" |
() => "rejected", // Rejected branch
);
}

export type PromiseWithResolvers<T> = {
promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
};

/**
* Creates a Promise with externalized resolve and reject functions.
*
* @returns An object containing:
* - promise: A new Promise
* - resolve: A function to resolve the Promise
* - reject: A function to reject the Promise
*
* @example
* const { promise, resolve, reject } = promiseWithResolvers<string>();
*
* // Later in your code:
* resolve('Hello, World!');
*
* // Or if an error occurs:
* reject(new Error('Something went wrong'));
*/
export function promiseWithResolvers<T>(): PromiseWithResolvers<T> {
let resolve: (value: T | PromiseLike<T>) => void;
let reject: (reason?: any) => void;

const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});

return { promise, resolve: resolve!, reject: reject! };
}
28 changes: 27 additions & 1 deletion test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, test, expect, jest } from "@jest/globals";
import { mergeObjects, sleep, promiseState } from "../lib/core/utils";
import { mergeObjects, sleep, promiseState, promiseWithResolvers } from "../lib/core/utils";

jest.setTimeout(2000);

Expand Down Expand Up @@ -130,3 +130,29 @@ describe("promiseState", () => {
expect(laterRejectedResult).toBe("rejected");
});
});

describe("promiseWithResolvers", () => {
test("resolves the promise", async () => {
const { promise, resolve } = promiseWithResolvers<string>();
resolve("Success");
await expect(promise).resolves.toBe("Success");
});

test("rejects the promise", async () => {
const { promise, reject } = promiseWithResolvers<string>();
reject(new Error("Failure"));
await expect(promise).rejects.toThrow("Failure");
});

test("resolve and reject functions are callable", () => {
const { resolve, reject } = promiseWithResolvers<string>();
expect(typeof resolve).toBe("function");
expect(typeof reject).toBe("function");
});

test("works with different types", async () => {
const { promise, resolve } = promiseWithResolvers<number>();
resolve(42);
await expect(promise).resolves.toBe(42);
});
});

0 comments on commit b2b6c3e

Please sign in to comment.