From a8cc72aea23e39b37e62e7eeaccf8f274b9bd473 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Fri, 8 Jan 2021 03:08:45 +0000 Subject: [PATCH] feat: add Task.wrapPromiseCreator --- docs/task-static.md | 25 +++++++++++++ src/Task/Task.ts | 10 +++++ src/Task/__tests__/wrapPromiseCreator.spec.ts | 37 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/Task/__tests__/wrapPromiseCreator.spec.ts diff --git a/docs/task-static.md b/docs/task-static.md index fd99b4bc..c5c3c090 100644 --- a/docs/task-static.md +++ b/docs/task-static.md @@ -310,6 +310,31 @@ type fromLazyPromise = ( {% endtab %} {% endtabs %} +## wrapPromiseCreator + +Given a function which returns a Promise, create a new function which given the same arguments will now return a Task instead. + +{% tabs %} +{% tab title="Usage" %} + +```typescript +const taskFetch = wrapPromiseCreator(fetch) +const task: Task = taskFetch(URL) +``` + +{% endtab %} + +{% tab title="Type Definition" %} + +```typescript +type wrapPromiseCreator = ( + fn: (...args: Args) => Promise, +) => (...args: Args): Task +``` + +{% endtab %} +{% endtabs %} + ## race Creates a task that will always run an array of tasks in **parallel**. The first task to finish is the resulting error or value. Useful for implementing network request timeouts by racing a task which fails in x milliseconds and a task which makes the request. diff --git a/src/Task/Task.ts b/src/Task/Task.ts index 66460385..5d5468e0 100644 --- a/src/Task/Task.ts +++ b/src/Task/Task.ts @@ -227,6 +227,15 @@ export const fromLazyPromise = ( getPromise: () => S | Promise, ): Task => succeedBy(getPromise).chain(fromPromise) +/** + * Given a function that returns a promise, return a new function that + * lazily returns a Task instead. + * @param fn A function which returns a promise + */ +export const wrapPromiseCreator = ( + fn: (...args: Args) => Promise, +) => (...args: Args): Task => fromLazyPromise(() => fn(...args)) + /** * Given a task, create a Promise which resolves when the task does. * @param task The task we will convert to a promise. @@ -700,6 +709,7 @@ export class Task implements PromiseLike { public static fromPromise = fromPromise public static fromPromises = fromPromises public static fromLazyPromise = fromLazyPromise + public static wrapPromiseCreator = wrapPromiseCreator public static race = race public static external = external public static emitter = emitter diff --git a/src/Task/__tests__/wrapPromiseCreator.spec.ts b/src/Task/__tests__/wrapPromiseCreator.spec.ts new file mode 100644 index 00000000..935052d1 --- /dev/null +++ b/src/Task/__tests__/wrapPromiseCreator.spec.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { wrapPromiseCreator } from "../Task" +import { ERROR_RESULT, SUCCESS_RESULT } from "./util" + +describe("wrapPromiseCreator", () => { + test("should succeed when a promise succeeds", async () => { + const resolve = jest.fn() + const reject = jest.fn() + + const promise = Promise.resolve(SUCCESS_RESULT) + const makePromise = (_a: string, _b: number) => promise + + const runTask = wrapPromiseCreator(makePromise) + runTask("test", 1).fork(reject, resolve) + + await promise + + expect(resolve).toBeCalledWith(SUCCESS_RESULT) + expect(reject).not.toBeCalled() + }) + + test("should fail when a promise fails", async () => { + const resolve = jest.fn() + const reject = jest.fn() + + const promise = Promise.reject(ERROR_RESULT) + const makePromise = (_a: number, _b: string) => promise + + const runTask = wrapPromiseCreator(makePromise) + runTask(1, "test").fork(reject, resolve) + + await promise.catch(() => void 0) + + expect(reject).toBeCalledWith(ERROR_RESULT) + expect(resolve).not.toBeCalled() + }) +})