Async composables
Composables can wrap asynchronous work, exposing data, loading and error refs that update as the request progresses.
In this page:
Syntax
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(true);
fetch(url)
.then((r) => r.json())
.then((d) => (data.value = d))
.catch((e) => (error.value = e))
.finally(() => (loading.value = false));
return { data, error, loading };
}
Async composables
A typical useFetch composable holds data, error and loading refs, starts the request when called or when its URL changes and updates the refs when it finishes. Components just read the refs, and the pattern removes repeated loading and error code.
Note:
Handle the error case and reset loading in a finally block.
Example: Async composables
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<p v-if="loading">Loading...</p>
<p v-else-if="error">Error: {{ error }}</p>
<p v-else>User: {{ data.name }}</p>
</div>
<script>
function useAsync(fn) {
const data = Vue.ref(null), error = Vue.ref(null), loading = Vue.ref(true);
fn().then((r) => (data.value = r)).catch((e) => (error.value = e.message)).finally(() => (loading.value = false));
return { data, error, loading };
}
Vue.createApp({
setup() {
return useAsync(() => new Promise((resolve) => setTimeout(() => resolve({ name: "Ada" }), 20)));
},
}).mount("#app");
console.log("at start:", document.querySelector("p").textContent);
setTimeout(() => console.log("after load:", document.querySelector("p").textContent), 100);
</script>
</body>
</html>
<!-- Output:
Rendered: User: Ada
console: at start: Loading...
console: after load: User: Ada
-->
Live Example
Related Topics
Common Mistakes
- Forgetting the loading state
- Not handling errors
- Racing requests when the URL changes quickly
Chapter Summary
- Expose data, error and loading refs
- Update refs when the promise settles
- Handle failures
- Reuse across components
🔒
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: