This gist provides a useAsyncComputed function which allows to create asynchronous dependencies on reactive values (using Vue 3's Composition API).
Requires at least Vue 3.0 and TypeScript 4.0.
import { ref } from 'vue'
import useAsyncComputed from './use-async-computed'
const packageName = ref('color-blend')
function getDownloads() {
return fetch(`https://api.npmjs.org/downloads/point/last-week/${packageName.value}`)
.then(response => response.json())
.then(result => result.downloads)
}
const [downloads] = useAsyncComputed(getDownloads, 0)Whenever packageName is updated, the downloads will stay the same until the returned computed promise resolves.
The second parameter passed to the useAsyncComputed function is optional. If provided, it is used as the initial value held by the computed ref until its first evaluation resolves.
The return value of useAsyncComputed is a two-item tuple. While the first item holds the ref containing the latest evaluation result, the second item is a boolean ref which tells whether the computed ref is currently being (re-)evaluated.
const [downloads, isGettingDownloads] = useAsyncComputed(getDownloads, 0)This may be used for displaying a loading indicator instead of the stale downloads value when the packageName changes.
The asyny computed callback receives an onCancel function as its first argument. It can be invoked with a callback which will be executed when a re-evaluation of the async computed value is triggered before the current has finished.
This can be used to clean up resources used for evaluation, e.g. we could cancel fetch requests to the npm API by adjusting our getDownloads function from the introductory example:
function getDownloads(onCancel) {
const abortController = new AbortController()
onCancel(() => {
abortController.abort()
})
return fetch(`https://api.npmjs.org/downloads/point/last-week/${packageName.value}`, {
signal: abortController.signal
})
.then(response => response.json())
.then(result => result.downloads)
}-
Just like Vue's built-in
computedfunction,useAsyncComputeddoes dependency tracking and is automatically re-evaluated when dependencies change.Note however that only dependencies referenced in the first call stack are considered for this. In other words: Dependencies which are accessed asynchronously are not triggering re-evaluation of the async computed value.
-
As opposed to Vue's built-in
computedfunction, re-evaluation of the async computed value is triggered whenever dependencies are changing, regardless whether its result is being used or not.
Had the same problem, computed properties in vue 3 are lazy and cached, and therefore great fit for async fetches. Sadly they do not support Promise returnsout of the box. Luckily there is a solution using vue's reactive components, so I created https://www.npmjs.com/package/vue3-async-computed plugin. Hope it helps. Usage is simple:
Here
profileproperty depends onuserIDand it's asynchronously computed whenuserIDchanges.