Simplify Frontend Request Logic with alova: Features, Hooks, and Code Examples
This article introduces alova, a JavaScript library for frontend developers that streamlines request handling by providing ready-made hooks for basic requests, pagination, form submission, captcha, file upload, auto-retry, SSE, and cross-component communication, illustrated with Vue code examples.
Hello, I am Gu Yun. Today I want to discuss how, when writing project code, we should focus more on business logic and let libraries or automation handle repetitive request logic, which can also be simplified.
Many developers encounter repetitive tasks such as pagination, form handling, debounce, polling, caching, loading states, error handling, captcha sending, file uploads, etc., often writing a lot of boilerplate code with axios or fetch.
alova offers a set of ready‑made request modules that manage these concerns automatically, allowing developers to concentrate on business logic.
alova's Lower Learning Curve
alova draws inspiration from axios and ahooks‑useRequest, making it easy to pick up.
alova official site (https://alova.js.org/zh-CN/).
Since its public release in April 2023, alova has attracted contributions worldwide.
If you like alovajs, please star the GitHub repository (https://github.com/alovajs/alova); it means a lot.
You can join the community chat or open Discussions/Issues on GitHub for support.
Basic Request
Basic requests provide loading, data, and error states automatically. Example using Vue 3:
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px"><span style="color: #aa0d91; line-height: 26px"><template></span>
<span style="color: #aa0d91; line-height: 26px"><div v-if="loading"></span>loading...<span style="color: #aa0d91; line-height: 26px"></div></span>
<span style="color: #aa0d91; line-height: 26px"><div v-else-if="error"></span>error: {{ error }}<span style="color: #aa0d91; line-height: 26px"></div></span>
<span style="color: #aa0d91; line-height: 26px"><div v-else></span>
<span style="color: #aa0d91; line-height: 26px"><span></span>id: {{ data.title }}<span style="color: #aa0d91; line-height: 26px"></span></span>
<span style="color: #aa0d91; line-height: 26px"><span></span>title: {{ data.time }}<span style="color: #aa0d91; line-height: 26px"></span></span>
<span style="color: #aa0d91; line-height: 26px"></div></span>
<span style="color: #aa0d91; line-height: 26px"></template></span>
<span style="color: #aa0d91; line-height: 26px"><script setup></span>
import { useRequest } from "alova";
const todoDetail = alova.Get("/todo", { params: { id: 1 } });
const { loading, data, error, onSuccess, onError, onComplete, send, abort, update } = useRequest(todoDetail);
onSuccess(event => { console.log("success", event); });
onError(event => { console.log("error", event); });
onComplete(event => { console.log("complete", event); });
<span style="color: #aa0d91; line-height: 26px"></script></span></code>useRequest automatically manages loading, data, and error states.
State‑Change Request
useWatcher listens to state changes (e.g., filters, search) and triggers requests with the same API as useRequest.
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">useWatcher(() => filterTodoList(page, keyword), [keyword, page], { debounce: [500, 0] });</code>Pre‑fetch Data
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { fetching, error, fetch } = useFetcher();
fetch(todoDetail);
</code>Pagination Request
usePagination handles page, pageSize, total, and related logic automatically.
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { loading, data, isLastPage, page, pageSize, pageCount, total } = usePagination((page, pageSize) => queryStudents(page, pageSize));
const handlePrevPage = () => { page.value--; };
const handleNextPage = () => { page.value++; };
const handleSetPageSize = () => { pageSize.value = 20; };
</code>Form Submission
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { form, send: submitForm, updateForm } = useForm(formData => submitData(formData), {
initialForm: { title: "", content: "", time: "" },
resetAfterSubmiting: true,
});
</code>Captcha Implementation
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { loading: sending, send: sendCaptcha } = useCaptcha(() => sendCaptcha(mobile), { initialCountdown: 60 });
</code>File Upload Strategy
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { fileList, loading, progress } = useUploader(({ file, name }) => uploadFile(file, name), {
limit: 3,
accept: ['png', 'jpg', 'gif'],
imageTempLink: true,
});
</code>Auto‑Refresh Data
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">useAutoRequest(todoDetail, {
enablePolling: 2000,
enableVisibility: true,
enableFocus: true,
enableNetwork: true,
throttle: 1000,
});
</code>Cross‑Component Request Strategy
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">// Component A creates proxy
useRequest(todoDetail, { middleware: actionDelegationMiddleware("someAction") });
// Component B triggers action
accessAction("someAction", actions => { actions.send(); });
</code>Request Retry Strategy
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { onRetry, onFail, stop } = useRetriableRequest(pay, {
retry(error) { return /network timeout/i.test(error.message); },
backoff: { delay: 2000 },
});
</code>SSE
<code style="padding: 16px; color: black; display: -webkit-box; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">const { readyState, data, eventSource, onMessage, onError, onOpen, on } =
useSSE(() => chatGPT(), { withCredentials: true, interceptByGlobalResponded: true });
</code>Conclusion
alova now supports Vue 2 options API as well; see the documentation for details.
Explore many runnable examples on the official site.
If you find this article helpful, please give it a like, comment, and consider starring the GitHub repository.
For more alova usage, visit the official website and contribute to the project.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
