Skip to main content

Request lifecycle, debounce và race condition

Search-as-you-type là nơi dễ phát sinh request chồng nhau nhất. Mục tiêu không phải “không bao giờ có request song song”, mà là UI cuối cùng phải phản ánh intent mới nhất của user.

Pattern an toàn

Debounce chặn phần lớn request không cần thiết trước khi chúng được tạo. Với mutation, ưu tiên disable action trong processing. Double-click hai lần vào “Thanh toán”, “Đặt chỗ” hoặc “Tạo đơn” không nên dựa vào frontend để đảm bảo uniqueness; backend vẫn cần idempotency/unique constraint/transaction phù hợp với domain.

Cancel không đồng nghĩa rollback

Nếu client cancel request sau khi server đã commit DB, cancel chỉ có thể ngừng phía client chờ response; nó không tự hoàn tác side effect ở server. Vì vậy những action có side effect quan trọng phải có transaction/business invariant ở backend.

Tách state

  • searchDraft: local state, thay đổi từng keypress.
  • filters: server props/URL, state đã commit vào navigation.
  • users: server state.
  • isFilterPanelOpen: local UI state.
Khi phân lớp như vậy, bạn ít phải “sync state” thủ công hơn.

Request lifecycle đầy đủ để debug

Một visit thực tế nên được nhìn như state machine:
Bạn có thể dùng lifecycle callback cho loading cục bộ:
onFinish phải là nơi cleanup vì nó chạy cho cả success và failure path.

Search race: debounce chưa phải toàn bộ câu chuyện

Trong DevTools hãy kiểm tra request chronology, URL và response timing. Nếu feature có nhiều async/prefetch request đồng thời, cân nhắc cancellation semantics của router thay vì tự ghép nhiều fetch không có owner.

Instrument duration ở một nơi

Production logger không nên ghi form payload/token/password.

Review checklist


Tài liệu chính thức

Nội dung thực chiến trong bài được xây dựng dựa trên API và nguyên lý của Inertia.js v3 Documentation. Khi áp dụng vào dự án, hãy đối chiếu API cụ thể với tài liệu chính thức theo phiên bản bạn đang sử dụng.