{"id":21851824,"url":"https://github.com/nberlette/defer","last_synced_at":"2026-05-18T11:34:37.188Z","repository":{"id":174869864,"uuid":"652465151","full_name":"nberlette/defer","owner":"nberlette","description":"Robust TypeScript API for deferred handling of Promises. Supports event listeners and custom state-specific callbacks.","archived":false,"fork":false,"pushed_at":"2023-06-13T05:02:21.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-21T18:32:17.543Z","etag":null,"topics":["async","defer","deferred","deferred-promise","deno","events","module","promises","typescript"],"latest_commit_sha":null,"homepage":"https://deno.land/x/defer","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nberlette.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"nberlette"}},"created_at":"2023-06-12T06:09:40.000Z","updated_at":"2023-06-13T05:08:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"a898dcee-2091-4985-a8cb-38692362d646","html_url":"https://github.com/nberlette/defer","commit_stats":null,"previous_names":["nberlette/defer"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/nberlette/defer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fdefer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fdefer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fdefer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fdefer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nberlette","download_url":"https://codeload.github.com/nberlette/defer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fdefer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33177092,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-18T09:27:30.708Z","status":"ssl_error","status_checked_at":"2026-05-18T09:27:28.300Z","response_time":71,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","defer","deferred","deferred-promise","deno","events","module","promises","typescript"],"created_at":"2024-11-28T01:11:29.500Z","updated_at":"2026-05-18T11:34:37.147Z","avatar_url":"https://github.com/nberlette.png","language":"TypeScript","funding_links":["https://ko-fi.com/nberlette"],"categories":[],"sub_categories":[],"readme":"# 🦖 defer\n\nBuilding upon the popular design pattern known as a Deferred Promise, `Defer`\nexposes `resolve` and `reject` methods on the Promise object itself, affording\nyou complete control over its resolution logic. It also emits a\n[number of events](#listening-to-promise-events) and supports\n[custom event handlers](#using-event-handler-methods), for tracking internal\nstate changes or triggering custom callbacks.\n\n## Features\n\n- Extends the built-in `Promise` class, giving you control over when it is\n  resolved or rejected.\n- Fires events when the Promise is fulfilled, rejected, settled, and any time\n  the internal state changes.\n- Retains full support of the native Promise API, including `then`, `catch`, and\n  `finally`, `Promise.all` and `Promise.allSettled`.\n- Provide event handlers as constructor options to initialize the Promise with\n  the handlers already attached.\n- Provide a custom executor function to initialize the Promise with custom\n  resolution logic.\n\n## Quick Start\n\n```ts\nimport { Defer } from \"https://deno.land/x/defer/mod.ts\";\n\nconst deferred = new Defer\u003cstring\u003e(); // =\u003e Deferred { \u003cpending\u003e }\ndeferred.resolve(\"Hello!\"); // =\u003e Deferred { \u003cfulfilled\u003e \"Hello!\" }\n```\n\n### `Defer` constructor signature\n\n```ts\nnew Defer\u003cT\u003e();\nnew Defer\u003cT\u003e(handlers: DeferEventHandlers\u003cT\u003e);\nnew Defer\u003cT\u003e(executor: DeferExecutor\u003cT\u003e, handlers?: DeferEventHandlers\u003cT\u003e);\n```\n\n\u003e **Note**: see the sections on\n\u003e [**_using event handler methods_**](#using-event-handler-methods) and\n\u003e [**_listening to promise events_**](#listening-to-promise-events) for more\n\u003e details on Defer's event-driven API.\n\n### `defer` factory function\n\nIf you'd like a callable alternative to using the `new` keyword, you can import\nand use the `defer` factory function instead. It has the same signature as the\n`Defer` constructor, and returns a new instance of `Defer`.\n\n```ts\nimport { defer } from \"https://deno.land/x/defer/mod.ts\";\n\nconst deferred = defer\u003cnumber\u003e(); // =\u003e Deferred { \u003cpending\u003e }\ndeferred.resolve(42); // =\u003e Deferred { \u003cfulfilled\u003e 42 }\n```\n\n## Usage and Examples\n\nCreating a \u003cb\u003e\u003cem\u003eDefer\u003c/em\u003e\u003c/b\u003ered Promise using the `Defer` class is very\nstraightforward; it follows the same design pattern made popular by its many\npredecessors. It provides the `resolve` and `reject` methods as properties of\nthe Promise object itself.\n\nTesting a simple deferred resolution:\n\n```ts\nconst d1 = new Defer\u003cnumber\u003e(); // suspended in \"pending\" state\nd1.state === \"pending\"; // =\u003e true\n\nd1.resolve(42);\n\nd1.state === \"fulfilled\"; // =\u003e true\nd1.value === 42; // =\u003e true\nd1; // =\u003e Deferred { \u003cfulfilled\u003e 42 }\n```\n\nTesting a simple deferred rejection:\n\n```ts\nconst d2 = new Defer\u003cstring\u003e();\n\nd2.reject(new Error(\"Something went wrong\"));\n\nd2.state === \"rejected\"; // =\u003e true\nd2.reason === \"Something went wrong\"; // =\u003e true\n\nd2; // =\u003e Deferred { \u003crejected\u003e reason: \"Something went wrong\" }\n```\n\n### Listening to Promise Events\n\nCurrently, the events that are emitted are `\"fulfilled\"`, `\"rejected\"`,\n`\"settled\"`, `\"statechange\"`, and `\"resolved\"` (an alias for fulfilled).\n\nYou can listen for any of the events using the standard `addEventListener` API.\nFor your convenience, the methods `addListener` / `on` are aliased to\n`addEventListener`, and `removeListener` / `off` are aliased to\n`removeEventListener`.\n\n```ts\nconst listener = ({ detail }) =\u003e {\n  console.log(detail.oldState, \"-\u003e\", detail.newState);\n};\n\nd.addEventListener(\"statechange\", listener); // long-hand\nd.addListener(\"statechange\", listener); // short-hand\nd.on(\"statechange\", listener); // shortest-hand\n```\n\nTo remove an existing listener:\n\n```ts\n// you **must** retain a reference to the original listener\nd.removeEventListener(\"statechange\", listener); // long-hand\nd.removeListener(\"statechange\", listener); // short-hand\nd.off(\"statechange\", listener); // shortest-hand\n```\n\n#### Debugging: observing all attached listeners\n\n```ts\nconst d = new Defer();\n\nd.on(\"statechange\", console.log);\nd.on(\"fulfilled\", console.log);\nd.on(\"rejected\", console.error);\n\n// get an array of all attached listeners\nd.listeners; // =\u003e { fulfilled: [ { callback: [Function log] } ], ... }\n```\n\n\u003e **Note**: this special property is **non-standard**, and only available in\n\u003e Deno environments. It will not be available in runtimes that use any other\n\u003e EventTarget API, such as browsers or Node.js.\n\n### Using Event Handler Methods\n\nYou can initialize a new instance with the event handlers already attached:\n\n```ts\nconst d = new Defer\u003c{ code: number; text: string }\u003e({\n  onfulfilled: (value) =\u003e console.debug(\"✅\", value),\n  onrejected: (reason) =\u003e console.error(\"⚠️\", reason),\n});\n```\n\nYou can also assign event handler methods on the Defer instance itself, which\nwill be called when the corresponding event is emitted:\n\n```ts\nd.onrejected = (reason) =\u003e {\n  console.error(\"Promise rejected:\", reason);\n};\n\n// handler method names must be all lowercase \nd.onsettled = function (value, state) =\u003e {\n  console.log({ value, state });\n  console.log(\"With `this`\": this.value, this.state);\n};\n```\n\n### Chaining Promise Methods\n\nDefer extends the built-in `Promise` class, so you can still use all the methods\nprovided by the Promise class, such as `then`, `catch`, and `finally`, to chain\nasynchronous operations.\n\n```ts\nconst deferred = new Defer\u003cnumber\u003e();\n\ndeferred\n  .then((value) =\u003e {\n    console.log(\"Promise resolved:\", value);\n    return value * 2;\n  })\n  .then((result) =\u003e {\n    console.log(\"Result:\", result);\n  })\n  .catch((error) =\u003e {\n    console.error(\"Promise rejected:\", error);\n  });\n\ndeferred.resolve(21);\n// =\u003e Promise resolved: 21\n// =\u003e Result: 42\n```\n\n## API Reference\n\nFor a complete API reference, including detailed information on events, event\nhandlers, and constructor overloads, please refer to the\n[API Documentation](https://deno.land/x/defer/mod.ts?doc).\n\n## Contributing\n\nContributions are welcome! If you have any bug reports, feature requests, or\nsuggestions, please open an issue on the\n[GitHub repository](https://github.com/nberlette/defer). If you want to\ncontribute code, feel free to open a pull request.\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n[**MIT**][MIT] © [**Nicholas Berlette**][nberlette]. All rights reserved.\n\n\u003c/div\u003e\n\n[MIT]: https://nick.mit-license.org \"MIT (c) 2023 Nicholas Berlette. All rights reserved.\"\n[nberlette]: https://github.com/nberlette \"Nicholas Berlette's GitHub profile\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnberlette%2Fdefer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnberlette%2Fdefer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnberlette%2Fdefer/lists"}