Vue Async Function delivers a compositional API for promise resolution and data fetching. It is inspired by the hooks functions of React Async and builds upon the Vue Composition API that is coming with Vue 3.0. Luckily, thanks to the official plugin you can build Vue apps with the new Composition API today with Vue 2.5+.
- Works with promises, async/await and the Fetch API
- Provides
abort
andretry
functions - Supports abortable fetch by providing an AbortController signal
- Reactive retry when arguments are
ref
-wrapped - Written in TypeScript, ships with type definitions
Installation
The current version expects your project to be built with vue-cli 4.0+. There's no support for previous verions. If your project is still built with 3.x, consider upgrading it. There's a detailed upgrading guide available.
In your Vue project, you need to install @vue/composition-api
together with vue-async-function
:
npm install --save @vue/composition-api vue-async-function
Or with Yarn:
yarn add @vue/composition-api vue-async-function
Then modify your entrypoint (often main.js
or main.ts
), as stated in the
Vue Composition API docs:
;; Vue;
After that, you can import useAsync
or useFetch
:
;
useAsync usage
Inside your setup()
function you can call useAsync
and provide it a function that returns a Promise as its first
argument. useAsync
returns three ref-wrapped properties: isLoading
, error
and data
. These are reactively updated
to match the state of the asynchronous process while resolution takes place. You also get two functions, retry
and
abort
that respectively retry the original asynchronous function or abort the current running function.
You can choose to return any of these values to use them in the component template or pass them to other functions to 'compose' your component. A simple example:
{ const data error isLoading retry abort = ; // ... return data error isLoading retry abort ; };
The second argument of useAsync
is optional. If provided, it is passed as first argument to the Promise returning
function.
{ return ; };
AbortController
useAsync
calls the asynchronous function for you with the optional first argument. Its second argument is an instance
of an AbortController signal. Your function
should listen to the 'abort' event on the signal and cancel its behavior when triggered.
In the following example, the wait
function simply waits for a configurable period and then resolves to a string. If
the abort
function returned from the useAsync
call is triggered, the timeout is cleared and the promise won't
resolve. It is up to you to decide if the promise needs to be rejected as well.
{ return { const timeout = ; signal; };} { return ; };
Note: calling retry
while the asynchronous function is not resolved calls abort
as well.
Reactive arguments
If you want your application to reactively respond to changing input values for useAsync
, you can pass in a
ref
-wrapped value as well as any parameter.
An example:
;// ... { const wrappedAsyncFunc = ; const wrappedParams = ; const data error isLoading retry abort = ; // ... ; // ... return data error isLoading retry abort ; };
Note that the triggered retry is the same as when you call retry
explicitly, so it will also call abort
for
unresolved functions.
useFetch usage
With useAsync
you could wrap the Fetch API easily. An example:
{ const headers = Accept: "application/json" ; const res = await ; if !resok throw res; return res;} { return ; };
This is such a common pattern that there is a special function for it: useFetch
. We can implement above example as
follows:
; { const id = 9; const url = `https://swapi.co/api/starships//`; const headers = Accept: "application/json" ; return ; };
useFetch
accepts the same arguments as the browser Fetch API. It will hook up the AbortController
signal for you and
based on the Accept
header it will choose between returning text()
or json()
results.
Reactive arguments
Above example shines even more with reactive arguments:
;; { const id = ; const computedUrl = ; const headers = Accept: "application/json" ; return id ... ; };
Here, the id
is made reactive. The url
is also reactive, using the computed
function that recomputes whenever any
of the reactive values is changed. We return both the id
and all of the results of useFetch
. Now we can for instance
bind the reactive id
with v-model
to an input field. Whenever the input field changes, it will cause the fetch to be
retried, aborting the current fetch if unresolved.
Full examples
useAsync
and Promise
example
useAsync and promises Loading... Error! {{ data }}
useAsync
and fetch
example
Retry Abort Loading... Error! {{ data }}
useFetch
example
Retry Abort Loading... Error! {{ data }}
useAsync
example with wrapped values
useAsync and promises, with value Retry Abort Loading... Error! {{ data }}
useFetch
example with wrapped values
useFetch with value Ship ID: Retry Abort Loading... Error! {{ data }}
See the examples folder for a demo project with all examples in JavaScript. See the examples-ts folder for a demo project with all examples in TypeScript.