{"id":21304969,"url":"https://github.com/maximilianmairinger/moreproms","last_synced_at":"2025-03-15T19:26:34.238Z","repository":{"id":202919402,"uuid":"708441433","full_name":"maximilianMairinger/moreProms","owner":"maximilianMairinger","description":"A collection of additional promise extending classes. Including a (from the outside) ResablePromise, CancelAblePromise and a latestLatent utility function.","archived":false,"fork":false,"pushed_at":"2024-04-12T22:35:29.000Z","size":79,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-09-15T11:28:48.003Z","etag":null,"topics":["able","cancel","cancelable","cancelablepromise","collection","latent","more","promise","promises","res","resable","resolve","resolveable"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/more-proms","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maximilianMairinger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2023-10-22T15:19:24.000Z","updated_at":"2024-01-07T11:53:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"dc6cc379-d3f6-4658-bed4-0e0049435b7d","html_url":"https://github.com/maximilianMairinger/moreProms","commit_stats":{"total_commits":57,"total_committers":1,"mean_commits":57.0,"dds":0.0,"last_synced_commit":"d05c67c4468a6ccc2e189a7d9230462554a555d4"},"previous_names":["maximilianmairinger/moreproms"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianMairinger%2FmoreProms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianMairinger%2FmoreProms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianMairinger%2FmoreProms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maximilianMairinger%2FmoreProms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maximilianMairinger","download_url":"https://codeload.github.com/maximilianMairinger/moreProms/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243779619,"owners_count":20346745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["able","cancel","cancelable","cancelablepromise","collection","latent","more","promise","promises","res","resable","resolve","resolveable"],"created_at":"2024-11-21T16:16:30.763Z","updated_at":"2025-03-15T19:26:34.208Z","avatar_url":"https://github.com/maximilianMairinger.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# More proms\r\n\r\nA collection of additional promise extending classes. Including a (from the outside) ResablePromise, CancelAblePromise and a latestLatent utility function.\r\n\r\n## Installation\r\n\r\n```shell\r\n $ npm i more-proms\r\n```\r\n\r\n## Usage\r\n\r\n### SettledPromise\r\n\r\n`SettledPromise` is a subclass of `Promise` that adds a `settled` property and an `onSettled` promise. The `settled` property indicates whether the promise has settled (resolved or rejected), and the `onSettled` promise resolves when the `SettledPromise` settles.\r\n\r\n```ts\r\nimport { SettledPromise } from \"more-proms\"\r\n\r\nconst promise = new SettledPromise((resolve, reject) =\u003e {\r\n  setTimeout(() =\u003e {\r\n    resolve(\"Hello, world!\")\r\n  }, 1000)\r\n})\r\n\r\nconsole.log(promise.settled) // false\r\n\r\npromise.onSettled.then(() =\u003e {\r\n  console.log(promise.settled) // true\r\n})\r\n```\r\n\r\n### ResablePromise\r\n\r\n`ResablePromise` is a subclass of `SettledPromise` that adds `res` and `rej` methods for resolving and rejecting the promise on the fly as consumer. This is only for convenience, as I see myself doing this (see the second example below) a lot. And this provides type safety without effort.\r\n\r\n```ts\r\nimport { ResablePromise } from \"more-proms\"\r\n\r\nconst prom = new ResablePromise()\r\n// later...\r\nprom.res()\r\n```\r\n\r\nSo you dont have to do this:\r\n\r\n```ts\r\nlet promRes\r\nconst prom = new Promise(res =\u003e promRes = res)\r\n// later ...\r\npromRes()\r\n```\r\n\r\n### CancelAblePromise\r\n\r\n`CancelAblePromise` is a subclass of `SettledPromise` that adds cancellation support. It has a `cancel` method for the consumer that can be used to cancel the promise. A canceled promise will never resolve nor will it reject.\r\n\r\nThe promise provider can provide a callback will only ever be called once, and wont be called after resolvement or rejection. This callback can be used to e.g. cancel an ongoing animation, or network request.\r\n\r\nNote how in this example the clearance of the timeout will have no effect, as a canceled promise wont resolve nor reject even if resolve is called after the timeout finishes. But the two example use cases from above could actually do something useful in the cancel callback.\r\n\r\n\r\n```ts\r\nimport { CancelAblePromise } from \"more-proms\"\r\n\r\nlet timeout\r\nconst p = new CancelAblePromise\u003cstring\u003e((resolve, reject) =\u003e {\r\n  timeout = setTimeout(() =\u003e {\r\n    resolve(\"Hello, world!\")\r\n  }, 1000)\r\n}, () =\u003e {\r\n  console.log(\"cancelled\")\r\n  clearTimeout(timeout)\r\n})\r\n\r\n\r\n// later\r\n\r\np.cancel()\r\n```\r\n\r\nNested cancellation are also supported. More specific: where nested promises created by `then` or `catch` methods are cancelled when the parent promise is cancelled. A nested example follows below. Note how `p1` is cancelled before `p2` resolve, hence only the `p1` will resolve, the `p2` will never resolve.\r\n\r\n```ts\r\nconst p1 = new CancelAblePromise\u003cstring\u003e((resolve, reject) =\u003e {\r\n  setTimeout(() =\u003e {\r\n    resolve(\"Hello, world\")\r\n  }, 1000)\r\n})\r\n\r\nconst p2 = p1.then(async (q) =\u003e {\r\n  console.log(1)\r\n  await delay(1000)\r\n  return q + \"!\"\r\n})\r\n\r\np2.then(() =\u003e {\r\n  console.log(2)\r\n})\r\n\r\ndelay(1500, () =\u003e {\r\n  p1.cancel()\r\n})\r\n```\r\n\r\n### latestLatent\r\n\r\n`latestLatent` is a function that takes a callback function and returns a similar function (acting as the given one) that only executes the latest callback and cancels previous callbacks. This is useful for scenarios where you have asynchronous operations that may be triggered multiple times, but you only want to process the result of the latest operation.\r\n\r\nA common use case would be a cleanup after an animation that should only be executed when no other animation has been triggered in the meantime.\r\n\r\n```ts\r\nimport { latestLatent } from \"more-proms\"\r\n\r\nconst showPopup = latestLatent(async () =\u003e {\r\n  element.css({display: \"block\"})\r\n  await element.animate({opacity: 1})\r\n  await closeButton.waitForClick()\r\n  await element.animate({opacity: 0})\r\n})\r\n\r\n\r\n// later\r\n\r\nshowButton.on(\"click\", () =\u003e {\r\n  showPopup().then(() =\u003e {\r\n    element.css({display: \"none\"})\r\n  })\r\n})\r\n\r\n```\r\n\r\nThis way you can be sure that the popup doesnt get `display: none`, when the user opens it again before it has been fully closed (the animation finishes).\r\n\r\nYou may have noticed that the location in your code where you want to `showPopup()` may have a different concern than ensuring that the popupElement is properly hidden. So, to keep the concerns where they belong, you can chain then calls directly on the showPopup provider (where it is declared).\r\n\r\n```ts\r\nconst showPopup = latestLatent(async () =\u003e {\r\n  element.css({display: \"block\"})\r\n  await element.animate({opacity: 1})\r\n  await closeButton.waitForClick()\r\n  await element.animate({opacity: 0})\r\n}).then(() =\u003e {\r\n  element.css({display: \"none\"})\r\n})\r\n\r\n\r\n// later\r\n\r\nshowButton.on(\"click\", () =\u003e {\r\n  showPopup()\r\n})\r\n```\r\n\r\nNote that these provider then calls change the output of the function (in this case `showPopup`), just like `then` calls on a promise change the output of the promise. So if you want to get the original functions output, you have to call the reference to the original function.\r\n\r\n```ts\r\nconst hello = latestLatent(async () =\u003e {\r\n  await delay(100)\r\n  return \"hello\"\r\n})\r\n\r\nconst helloWorld = hello.then(async (w) =\u003e {\r\n  await delay(100)\r\n  return w + \" world\"\r\n})\r\n\r\n// later\r\n\r\nhello().then((w) =\u003e {\r\n  console.log(w) // hello\r\n})\r\n\r\n\r\n\r\nawait delay(1000) // lets begin another example\r\n\r\n\r\n\r\n// here both hello and helloWorld are called, since the delay between them is large enough for hello() to settle.\r\n\r\nhello().then((w) =\u003e {\r\n  console.log(w) // hello\r\n})\r\n\r\nawait delay(150)\r\n\r\nhelloWorld().then((w) =\u003e {\r\n  console.log(w) // hello world\r\n})\r\n\r\n\r\nawait delay(1000) // lets begin another example\r\n\r\n\r\n\r\n// here only hello is called, since the delay between them is not large enough for helloWorld() to settle.\r\n\r\nhelloWorld().then((w) =\u003e {\r\n  console.log(w) // wont ever get here\r\n})\r\n\r\nawait delay(150)\r\n\r\nhello().then((w) =\u003e {\r\n  console.log(w) // hello\r\n})\r\n```\r\n\r\n\r\n## Contribute\r\n\r\nAll feedback is appreciated. Create a pull request or write an issue.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximilianmairinger%2Fmoreproms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaximilianmairinger%2Fmoreproms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaximilianmairinger%2Fmoreproms/lists"}