{"id":18750716,"url":"https://github.com/cafebazaar/async-actions","last_synced_at":"2025-07-22T13:34:30.487Z","repository":{"id":134932114,"uuid":"295642192","full_name":"cafebazaar/async-actions","owner":"cafebazaar","description":"A more efficient way of handling async actions and loading/error states without code duplications in Vue.","archived":false,"fork":false,"pushed_at":"2023-03-05T12:27:59.000Z","size":1298,"stargazers_count":20,"open_issues_count":5,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-05T06:38:39.225Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@cafebazaar/async-actions","language":"JavaScript","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/cafebazaar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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}},"created_at":"2020-09-15T06:59:56.000Z","updated_at":"2022-09-09T05:10:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"e8a02ca0-bc36-4015-bb29-e09a0d31f575","html_url":"https://github.com/cafebazaar/async-actions","commit_stats":{"total_commits":82,"total_committers":5,"mean_commits":16.4,"dds":0.5121951219512195,"last_synced_commit":"74e0710ed08abb91af30d614c3575f30d2007c7b"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/cafebazaar/async-actions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafebazaar%2Fasync-actions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafebazaar%2Fasync-actions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafebazaar%2Fasync-actions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafebazaar%2Fasync-actions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cafebazaar","download_url":"https://codeload.github.com/cafebazaar/async-actions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cafebazaar%2Fasync-actions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266506198,"owners_count":23940019,"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","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-07T17:12:54.575Z","updated_at":"2025-07-22T13:34:30.460Z","avatar_url":"https://github.com/cafebazaar.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/2771377/95751339-57fbe900-0cab-11eb-8eda-39d8e2807fca.png\" /\u003e\n\u003c/p\u003e\n\n## Overview\n\nHandling async actions(like API calls) is so tedious. Showing loading state and handling options like debouncing needs a lot of code duplications.\n\nAsync-Actions proposes a more efficient way of handling those actions without code duplications.\n\n![Async Action Before/After Comparison](https://user-images.githubusercontent.com/2771377/96008074-0a6ab200-0e4c-11eb-8440-90026e4cf449.png)\n\n## How It Works\n\nActions are just simple functions. Async-Actions adds `state`, `error`, `pending` and `data` properties to your functions and dynamically updates these properties.\n\n#### Action lifecycle and possible values of the `state` property\n\n| Value        | Description                                                                                           |\n| ------------ | ----------------------------------------------------------------------------------------------------- |\n| notInitiated | Action has not been called yet.                                                                       |\n| pending      | Action has been called, but it has not been completed yet.                                            |\n| fulfilled    | Action has been completed successfully, and the result value is accessible using the `data` property. |\n| rejected     | Action has been rejected with an error which is accessible using `error` property.                    |\n\nFor checking if an action is in the **pending** status or not, you can also use the `pending` property on the action, which is more convenient.\n\n## Installation\n\nYou can install Async-Actions with NPM or Yarn.\n\n```bash\nnpm install @cafebazaar/async-actions --save\n```\n\nor\n\n```bash\nyarn add @cafebazaar/async-actions\n```\n\n## Usage\n\nYou can use Async-Actions in [pure JS](#pure-js). Also there are built in extensions for [Vue.js](#vuejs) and [Svelte](#svelte).\n\n### Vue.js\n\n`Vue.observable` provided by default as the observable function in the Vue version, and you don't need to pass it. There are two ways to use Async-Actions in a Vue.js project.\n\n#### 1. Define actions in component options\n\nFor declaring async-actions in this way, you need to import the plugin and `use` it as a Vue plugin to enable the functionality globally on all components.\n\n```javascript\nimport Vue from 'vue';\nimport AsyncActions from '@cafebazaar/async-actions/vue';\n\nVue.use(AsyncActions);\n```\n\nThen, you can define async-actions in all components using `asyncActions` property.\n\n```javascript\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cdiv v-if=\"getUsers.state === 'pending'\"\u003e\n      Fetching Users List. Please Wait...\n    \u003c/div\u003e\n    \u003cdiv v-else-if=\"getUsers.error\"\u003e\n      Oops. Somthing Went Wrong :(\n    \u003c/div\u003e\n    \u003cdiv v-else\u003e\n      \u003cul\u003e\n        \u003cli v-for=\"user in getUsers.data\" :key=\"user.id\"\u003e\n          {{ user.name }}\n        \u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n  name: 'UsersList',\n  asyncActions: {\n    getUsers: {\n      handler() {\n        return someApiCall();\n      },\n      immediate: true,\n      initialData: [],\n      // other options...\n    },\n  },\n};\n\u003c/script\u003e\n```\n\nThe List of all options is available [here](#options).\n\nIf an action does not need any options, you can define it as a function for the sake of simplicity.\n\n```javascript\n\u003cscript\u003e\nimport { loginApi } from './api';\n\nexport default {\n  name: 'Login',\n  asyncActions: {\n    login() {\n      return loginApi();\n    }\n  },\n};\n\u003c/script\u003e\n```\n\n#### Options\n\n| Property    | Description                                                             | type     | Required | Default |\n| ----------- | ----------------------------------------------------------------------- | -------- | -------- | ------- |\n| handler     | action's handler                                                        | function | true     |         |\n| immediate   | determines handler function should be called immediately after creation | boolean  | false    | false   |\n| debounce    | debounce time in miliseconds                                            | number   | false    | 0       |\n| initialData | initial value of `data` property of action                              | any      | false    | null    |\n\n#### 2. Create asyncActions outside of components\n\nIn this way, you can create asyncActions anywhere and use them as regular functions.\n\n```javascript\n// usersActions.js\n\nimport { asyncAction } from '@cafebazaar/async-actions/vue';\nimport { someApiCall } from './api';\n\nexport const getUsers = asyncAction(() =\u003e someApiCall(), {\n  initialData: [],\n});\n```\n\nAnd after that, you can import and use it inside Vue components:\n\n```javascript\n\u003ctemplate\u003e\n  \u003cdiv\u003e\n    \u003cdiv v-if=\"getUsersAction.state === 'pending'\"\u003e\n      Fetching Users List. Please Wait...\n    \u003c/div\u003e\n    \u003cdiv v-else-if=\"getUsersAction.error\"\u003e\n      Oops. Somthing Went Wrong :(\n    \u003c/div\u003e\n    \u003cdiv v-else\u003e\n      \u003cul\u003e\n        \u003cli v-for=\"user in getUsersAction.data\" :key=\"user.id\"\u003e\n          {{ user.name }}\n        \u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nimport { getUsers } from './usersActions';\n\nexport default {\n  name: 'UsersList',\n  computed: {\n    getUsersAction(){\n      return getUsers;\n    }\n  },\n  created(){\n    getUsers();\n  }\n};\n```\n\n### Svelte\n\nIn the Svelte version, `Store.writable` is used for every observable prop(`state`, `data`, and `error`) and, you don't need to provide `observableFn`. You can simply do:\n\n```html\n\u003cscript\u003e\n  import asyncAction from '@cafebazaar/async-actions/src/svelte';\n  let myPromise = asyncAction(function () {\n    return new Promise((resolve) =\u003e {\n      setTimeout(() =\u003e resolve('My Data!!'), 5000);\n    });\n  }, options);\n\n  let { state, data, error } = myPromise;\n\n  // execute async function\n  myPromise();\n\u003c/script\u003e\n\n\u003cmain\u003e\n  \u003cul\u003e\n    \u003cli\u003eStatus: {$state}\u003c/li\u003e\n    \u003cli\u003eData: {$data}\u003c/li\u003e\n    \u003cli\u003eError: {$error}\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/main\u003e\n```\n\nThe List of all options is available [here](#options).\n\nYou can use asyncAction outside of svelte file and import it and use it directly inside DOM.\n\n### Pure JS\n\nYou can define an async-action using `asyncAction` method which gets a handler function and configuration options as its parameters. When using the pure version, you must provide an observable function which used for updating action properties.\n\n```javascript\nimport { asyncAction } from '@cafebazaar/async-actions/pure';\nimport customObservable from 'utils/observable';\n\nconst myAsyncAction = asyncAction(\n  Promise.resolve('Hello'),\n  options,\n  customObservable\n);\n```\n\nList of all options are available [here](#options).\n\n## License\n\n[MIT](https://github.com/cafebazaar/async-actions/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcafebazaar%2Fasync-actions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcafebazaar%2Fasync-actions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcafebazaar%2Fasync-actions/lists"}