Skip to content

Instantly share code, notes, and snippets.

@patrixr
Last active August 4, 2021 07:57
Show Gist options
  • Save patrixr/5130974a336adb48fec05de962ce5a87 to your computer and use it in GitHub Desktop.
Save patrixr/5130974a336adb48fec05de962ce5a87 to your computer and use it in GitHub Desktop.
Vue UseAsync
import { onMounted, ref } from 'vue'
type AsyncFunc = () => Promise<any>
type ReturnType<F extends AsyncFunc> = F extends () => Promise<infer R> ? R : any
type UseAsyncOptions = {
lazy?: boolean
}
export function useAsync<F extends AsyncFunc>(fn: F, opts?: UseAsyncOptions) {
const error = ref<Error|null>(null);
const loading = ref(false);
const data = ref<ReturnType<F>|null>(null)
const trigger = async () => {
loading.value = true;
try {
data.value = await fn();
} catch (e) {
error.value = e;
} finally {
loading.value = false;
}
}
onMounted(() => {
if (opts?.lazy) return;
trigger();
})
return [data, loading, error, trigger];
}
useAsync.lazy = <F extends AsyncFunc>(fn: F) => {
return useAsync(fn, {
lazy: true
})
}
// EXAMPLE USAGE
export default defineComponent({
name: 'App',
setup() {
const [data, loading, error] = useAsync(async () => {
const { result } = await apiCall();
return result;
})
return {
loading,
error,
data
}
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment