{"id":16823472,"url":"https://github.com/digitalbrainjs/axiospromise","last_synced_at":"2025-11-06T09:30:29.545Z","repository":{"id":66168672,"uuid":"603851255","full_name":"DigitalBrainJS/AxiosPromise","owner":"DigitalBrainJS","description":"Lightweight Promises/A+ compatible implementation with cancellation, sync mode, timeouts, coroutines and signals support","archived":false,"fork":false,"pushed_at":"2024-09-13T21:12:59.000Z","size":1036,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-03T13:23:04.032Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/DigitalBrainJS.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-02-19T18:48:52.000Z","updated_at":"2024-09-13T21:12:31.000Z","dependencies_parsed_at":"2024-03-19T01:25:26.206Z","dependency_job_id":"de6cf8f7-6848-44bf-860f-ea7da1427400","html_url":"https://github.com/DigitalBrainJS/AxiosPromise","commit_stats":{"total_commits":37,"total_committers":3,"mean_commits":"12.333333333333334","dds":"0.18918918918918914","last_synced_commit":"7ffccf13ac26217ea82516f7b942457bb907ee21"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalBrainJS%2FAxiosPromise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalBrainJS%2FAxiosPromise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalBrainJS%2FAxiosPromise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalBrainJS%2FAxiosPromise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DigitalBrainJS","download_url":"https://codeload.github.com/DigitalBrainJS/AxiosPromise/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239488698,"owners_count":19647255,"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":[],"created_at":"2024-10-13T11:08:06.366Z","updated_at":"2025-11-06T09:30:29.516Z","avatar_url":"https://github.com/DigitalBrainJS.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Axios Promise\n\nLightweight Promises/A+ compatible implementation with cancellation, sync mode, timeouts, coroutines and signals support\n\n\u003cdiv align=\"center\"\u003e\n\n[![npm version](https://img.shields.io/npm/v/axios-promise.svg?style=flat-square)](https://www.npmjs.org/package/axios-promise)\n[![Build status](https://img.shields.io/github/actions/workflow/status/digitalbrainjs/axiospromise/ci.yml?branch=master\u0026label=CI\u0026logo=github\u0026style=flat-square)](https://github.com/digitalbrainjs/axios-promise/actions/workflows/ci.yml)\n[![Coverage Status](https://coveralls.io/repos/github/DigitalBrainJS/AxiosPromise/badge.svg?branch=master)](https://coveralls.io/github/DigitalBrainJS/AxiosPromise?branch=master)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/axios-promise?style=flat-square)](https://bundlephobia.com/package/axios-promise@latest)\n[![npm downloads](https://img.shields.io/npm/dm/axios-promise.svg?style=flat-square)](https://npm-stat.com/charts.html?package=axios-promise)\n\n\u003c/div\u003e\n\n## Installing\n\nUsing npm:\n\n```bash\n$ npm install axios-promise\n```\n\n```js\nimport {AxiosPromise, AxiosPromiseSync} from 'axios-promise';\n```\n\n## Intro\n\n`AxiosPromise` is a `Promises/A+` compatible implementation with cancellation API extension, \ntherefore, to start using it, you do not need to additionally learn a new and complex API.\nAll you need to know that every promise:\n- has `.cancel([reason])` method\n- has `.onCancel` subscriber for optional aborting long-running asynchronous operation inside a promise \n\n## Basic Examples\n\n[Live demo](https://playcode.io/1424670)\n\n```js\nimport { AxiosPromise } from 'axios-promise';\n\nconst p = new AxiosPromise((resolve, reject, {onCancel}) =\u003e {\n  const timer = setTimeout(resolve, 1000, 123);\n  onCancel((reason) =\u003e {\n    console.log('clear timer', reason);\n    clearTimeout(timer);\n  });\n}).then(\n  v =\u003e console.log(`Done: ${v}`), \n  e =\u003e console.warn(`Fail: ${e}`)\n);\n\nsetTimeout(()=\u003e p.cancel(), 500);\n```\n\nInstead of using the plain `onCancel` listener you can subscribe to a `AbortSignal` instance for the same purpose.\n\nYou can also set onCancel handler by returning it from the promise executor function:\n\n[Live demo](https://playcode.io/1449598)\n\n```js\nimport { AxiosPromise } from 'axios-promise';\n\nconst p = new AxiosPromise((resolve) =\u003e {\n  const timer = setTimeout(resolve, 1000, 123);\n  return (reason) =\u003e {\n    console.log('clear timer', reason);\n    clearTimeout(timer);\n  };\n}).then(\n  v =\u003e console.log(`Done: ${v}`), \n  e =\u003e console.warn(`Fail: ${e}`)\n);\n\nsetTimeout(()=\u003e p.cancel(), 500);\n```\n\nSee [Live Playground](https://playcode.io/1411507) ([Version for Node](https://codesandbox.io/p/sandbox/quiet-sunset-km5o2b))\n\n```js\nfunction cancelableFetch(url) {\n    return new AxiosPromise((resolve, reject, {signal}) =\u003e {\n        fetch(url, {signal}).then(resolve, reject)\n    });\n}\n\nconst p = cancelableFetch('http://httpbin.org/get').then((response) =\u003e response.json()).then(console.log);\n\n// p.cancel();\n```\n\nOR\n\n````js\nconst p = cancelableFetch('http://httpbin.org/get').then(function*(response) {\n  const json = yield response.json();\n  console.log(json);\n});\n````\n\nOR\n\n````js\nconst requestJSON = AxiosPromise.promisify(function*({signal}, url) {\n  const response = yield fetch(url, {signal});\n  const json = yield response.json();\n  console.log(json);\n}, {scopeArg: true});\n\nconst p = requestJSON('http://httpbin.org/get');\n\n// p.cancel();\n````\n\n## Features\n\n- no dependencies, less than `5KB` gzipped\n\n- provides two classes: \n    - `AxiosPromise` - Promises/A+ compatible implementation\n    - `AxiosPromiseSync` - a subclass of `AxiosPromise` but with synchronous chains resolution\n\n- recursive cancellation by rejecting the deepest promise in the chain with a special `CanceledError` reason\n\n    \u003e Note: AxiosPromise passes an additional scope argument to the executor function and `then` handlers, which refers to the promise context.\n    \n    ```js\n    const p = new AxiosPromise((resolve, reject, scope) =\u003e {\n      const timer = setTimeout(resolve, 1000);\n      scope.onCancel(() =\u003e clearTimeout(timer));\n    }).then((value, scope) =\u003e console.log(value), (reason, scope) =\u003e console.warn(reason));\n    \n    setTimeout(() =\u003e p.cancel(), 100);\n    ```\n  \n- cancellable delay helper\n    ```js\n    await AxiosPromise.delay(1000, 'foo');\n    ```  \n\n- timeouts - each promise has a `timeout` setter\n\n    ```js\n    await AxiosPromise.delay(1000).timeout(100);\n    ```\n\n- subscribing to an external `AbortSignal`\n\n    ```js\n    const controller = new AbortController();\n    AxiosPromise.delay(1000).listen(controller.signal).then(console.log, console.warn);\n    setTimeout(() =\u003e controller.abort(), 100);\n    ```\n\n- Providing an `AbortSignal` to subscribe - every promise has a `signal` getter that you can subscribe to\n\n    ```js\n    AxiosPromise.delay(1000).timeout(100).signal.addEventListener('abort', () =\u003e console.log('canceled'));\n    ```\n\n- atomic chains - makes sub-chain not cancellable when canceled from upper chain\n    - `AWAIT = false` mode (default value) - waits for the atomic sub-chain to resolve before canceling the upper chain\n\n        ```js\n        const p = AxiosPromise.delay(1000).atomic(false).then(() =\u003e AxiosPromise.delay(1000)).then(console.log, console.warn);\n        \n        p.cancel(); // will wait for the first promise and then cancel the rest\n        ```\n\n    - `DETACHED = true` mode - does not wait for the atomic sub-chain to resolve, but cancels the upper chain.\n\n        ```js\n        const p = AxiosPromise.delay(1000).atomic(true).then(() =\u003e AxiosPromise.delay(1000)).then(console.log, console.warn);\n        \n        p.cancel(); // will keep the first promise pending and cancel the rest of the chain\n        ```\n- coroutines - write flat cancelable code as if you were using ECMA asynchronous functions\n\n    ```js\n    const myAsyncFunc = AxiosPromise.promisify(function*(str) {\n      const newStr = yield AxiosPromise.delay(1000, 'Hello ') + str;\n      return newStr;\n    });\n  \n    const p = myAsyncFunc(123).then(function*(value) {\n      yield AxiosPromise.delay(1000);\n      console.log(`It supports generators in then method, result is:`, value);\n    });\n  \n    //p.cancel();\n    ```\n- `.all` method will cancel all pending promises if one rejected \n- `.race` method will cancel all pending promises if one resolved \n- `finally` method handles a status entry as the first argument\n\n## Error handling\n\nCancelling chain means rejecting its deepest promise with a `CanceledError` reason.\n\n```js\nconst p = new AxiosPromise((resolve, reject, {onCancel}) =\u003e {\n  const timer = setTimeout(()=\u003e {\n    Math.random() \u003e 0.5 ? reject(new Error('Oops!')) : resolve('foo');\n  }, 1000);\n  onCancel(() =\u003e clearTimeout(timer));\n}).then((value) =\u003e {\n  return value + 'bar';\n}).catch((err) =\u003e {\n  // re-throw the error if this is an instance of CanceledError to handle it with upper chains\n  CanceledError.rethow(err);\n  console.log('Error', err)\n});\n```\n\n\u003e Note: uncaught `CanceledError` rejection won't lead to `unhandledrejection` warning \n\n## Helpers\n### bottleneck\n\nA helper that creates a simple queue by decorating an asynchronous function.\n\n`bottleneck(fn, options?: {concurrency: number, cancelRunning: boolean, sync: boolean, timeout: number, taskTimeout: number, queueTimeout: number})`\n\n```js\n  const fn = bottleneck(function* () {\n    console.log('start');\n    yield AxiosPromise.delay(2000);\n    console.log('end');\n    return 'foo'\n  }, {concurrency: 1});\n\n  const results = await Promise.allSettled([\n    fn(),\n    fn(),\n    fn()\n  ]);\n\n  console.log(results.map(({status, reason, value}) =\u003e status + ' : ' + (reason?.toString() || value)))\n```\nLog:\n```\nstart\nend\nstart\nend\nstart\nend\n[ 'fulfilled : foo', 'fulfilled : foo', 'fulfilled : foo' ]\n````\n\n### Options\n\n`cancelRunning` - cancel running tasks if the concurrency limit is reached\n\n```js\nconst fn = bottleneck(function* () {\n  console.log('start');\n  yield AxiosPromise.delay(2000);\n  console.log('end');\n  return 'foo'\n}, {cancelRunning: true, concurrency: 1});\n\nconst results = await Promise.allSettled([\n  fn(),\n  fn(),\n  fn()\n]);\n\nconsole.log(results.map(({status, reason, value}) =\u003e status + ' : ' + (reason?.message || value)))\n```\nLog:\n```\nstart\nend\n[\n  'rejected : CanceledError: task limit reached',\n  'rejected : CanceledError: task limit reached',\n  'fulfilled : foo'\n]\n```\n\n`timeout/taskTimeout/queueTimeout` - use AxiosPromiseSync instead AxiosPromise\n\nSets appropriate timeouts\n\n```js\n(async () =\u003e {\n  const fn = bottleneck(function* (t = 2000) {\n    console.log('start');\n    yield AxiosPromise.delay(t);\n    console.log('end');\n    return 'foo'\n  }, {concurrency: 1, taskTimeout: 1000});\n\n  const results = await Promise.allSettled([\n    fn(),\n    fn(),\n    fn(500)\n  ]);\n\n  console.log(results.map(({status, reason, value}) =\u003e status + ' : ' + (reason?.toString() || value)))\n})();\n```\n\nLog:\n\n```\nstart\nstart\nstart\nend\n[\n  'rejected : TimeoutError: task timeout',\n  'rejected : TimeoutError: task timeout',\n  'fulfilled : foo'\n]\n```\n\n### Manual cancellation\n\n```js\n  const fn = bottleneck(function* (t = 2000) {\n    console.log('start');\n    yield AxiosPromise.delay(t);\n    console.log('end');\n    return 'foo'\n  }, {concurrency: 1});\n\n  const tasks = [\n    fn(),\n    fn(),\n    fn()\n  ];\n\n  setTimeout(() =\u003e {\n    tasks[1].cancel('Oops!');\n  }, 500);\n\n  const results = await Promise.allSettled(tasks);\n\n  console.log(results.map(({status, reason, value}) =\u003e status + ' : ' + (reason?.toString() || value)))\n```\n\nLog:\n\n```\nstart\nend\nstart\nend\n[\n  'fulfilled : foo',\n  'rejected : CanceledError: Oops!',\n  'fulfilled : foo'\n]\n```\n\n## License\n\nThe MIT License Copyright (c) 2023 Dmitriy Mozgovoy robotshara@gmail.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbrainjs%2Faxiospromise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalbrainjs%2Faxiospromise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalbrainjs%2Faxiospromise/lists"}