await Composition API
await Vue 3 🙏
Martin Malinda
- TopMonks - SPAs - Ember / React
- Leadfeeder - Remote - SPA - Ember
- GreenFox Academy - .NET , Java, React
- GoOut - Vue / Nuxt 🎉
goout.cz
Praha, Vinohrady
Composition API
- Oficiálně k dispozici ve Vue 3
- Ve Vue2 přes plugin
- umožňuje... composition 😎
- useThis(), useThat()...
- ref, computed, onMounted, onCreated...
Asynchronní logika?!
- AJAX requests
- scheduling
- timeouts
- intervals
- polling
- throttling
- debouncing
- concurrency
- lazy loading
- infinite scroll
- autocomplete
- type-ahead search
- background reload
- resilient AJAX
- a tak...
User je asynchronní....
Server je asynchronní...
A my si to ještě komplikujeme (lazy loading, scheduling...)
export default defineComponent({
setup() {
const data = ref(null);
axios('/api/users').then((response) => {
data.value = response.data;
});
return { data };
}
});
Loading substate???
Error handling???
<template>
<div>
<div v-for="user in data">
{{ user.name }}
</div>
</div>
</template>
export default defineComponent({
setup() {
const data = ref(null);
const error = ref(null);
const isLoading = ref(true);
axios('/api/users').then(response => {
data.value = response.data;
isLoading.value = false;
}).catch(e => {
error.value = e;
});
return { data, error, isLoading };
}
});
export default defineComponent({
setup() {
const data = ref(null);
const error = ref(null);
const isLoading = ref(true);
axios('/api/users').then(response => {
data.value = response.data;
}).catch(e => {
error.value = e;
}).finally(() => {
isLoading.value = false;
});
return { data, error, isLoading };
}
});
Retry??
export default defineComponent({
setup() {
const data = ref(null);
const error = ref(null);
const isLoading = ref(false);
const fetchUsers = async () => {
error.value = null;
isLoading.value = true;
try {
isLoading.value = true;
const response = await axios('/api/users');
data.value = response.data;
} catch (e) {
error.value = e;
} finally {
isLoading.value = false;
}
};
fetchUsers();
return { data, error, isLoading, fetchUsers };
}
});
<template>
<div>
<div v-if="error">
<p> {{ error.message }} </p>
<button @click="fetchUsers">Try again</button>
</div>
<div v-else-if="isLoading"> Loading ... </div>
<div v-else>
{{ data }}
</div>
</div>
</template>
🤔
function useAsync(cb = () => {}) {
const data = ref(null);
const error = ref(null);
const isLoading = ref(false);
const run = async () => {
error.value = null;
isLoading.value = false;
try {
isLoading.value = true;
data.value = await cb();
} catch (e) {
error.value = e;
} finally {
isLoading.value = false;
}
};
return { data, error, isLoading, run };
}
export default defineComponent({
setup() {
const { data, error, isLoading, run: fetchUsers } = useAsync(async () => {
const response = await axios('/api/users');
return data.value;
});
return { data, error, isLoading, fetchUsers };
},
});
import { useAsyncState } from '@vueuse/core'
import axios from 'axios'
export default {
setup() {
const { state, ready } = useAsyncState(
axios
.get('https://jsonplaceholder.typicode.com/todos/1')
.then(t => t.data),
{
id: null,
},
)
return { state, ready }
},
}
DRYing the template?
<template>
<Promised :promise="usersPromise">
<template v-slot:pending>
<p>Loading...</p>
</template>
<template v-slot="data">
<ul>
<li v-for="user in data">{{ user.name }}</li>
</ul>
</template>
<template v-slot:rejected="error">
<p>Error: {{ error.message }}</p>
</template>
</Promised>
</template>
vue-promised
export default defineComponent({
setup() {
const usersPromise = axios.get('/api/users');
return { usersPromise };
}
});
🤔
Promises? Refs?
Ani jedno?
<Suspense />
export default defineComponent({
async setup() {
const users = await fetchUsers();
return { users };
}
});
<div v-for="user in users">
{{ user.name }}
</div>
export default defineComponent({
setup() {
const error = ref(null);
onErrorCaptured(caughtError => {
error.value = caughtError;
return true;
})}
return { error };
}
});
<template>
<div v-if="error"> {{ error.message }}</div>
<Suspense v-else>
<template #default>
<Admins />
<Users />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>
</template>
<ChildComponent />
<ParentComponent />
Saving data?
Retry?
Concurrency management?
🤯
Flexibility?
vue-concurrency
export default defineComponent({
setup() {
const getUsersTask = useTask(function * () {
const response = yield axios('/api/users');
return response.data.users;
});
getUsersTask.perform();
return { getUsersTask };
}
});
<template>
<div>
<div v-if="getUsersTask.isRunning">
Loading ...
</div>
<div v-else-if="getUsersTask.isError">
<p>{{ getUsersTask.last.error }}</p>
<button @click="task.perform">
Try again
</button>
</div>
<div v-else v-for="user in getUsersTask.last.value">
{{ user.name }}
</div>
</div>
</template>
<template>
<AsyncContent :task="getUsersTask" v-slot="{ lastValue }">
<div v-for="user in lastValue">
{{ user.name }}
<div>
</AsyncContent>
</template>
📖
await Composition API
By Martin Malinda
await Composition API
- 881