Các phương pháp hay nhất để duy trì trạng thái ứng dụng bằng IndexedDB

Tìm hiểu các phương pháp hay nhất để đồng bộ hoá trạng thái ứng dụng giữa IndexedDB và các thư viện quản lý trạng thái phổ biến.

Khi người dùng tải một trang web hoặc ứng dụng lần đầu, thường có một lượng công việc kha khá liên quan đến việc xây dựng trạng thái ứng dụng ban đầu dùng để kết xuất giao diện người dùng. Ví dụ: đôi khi ứng dụng cần xác thực người dùng ở phía máy khách, sau đó đưa ra một số yêu cầu API trước khi có tất cả dữ liệu cần thiết để hiển thị trên trang.

Việc lưu trữ trạng thái ứng dụng trong IndexedDB có thể là một cách hiệu quả để tăng tốc thời gian tải cho những lượt truy cập lặp lại. Sau đó, ứng dụng có thể đồng bộ hoá với mọi dịch vụ API trong nền và cập nhật giao diện người dùng bằng dữ liệu mới một cách lười biếng, sử dụng chiến lược stale-while-revalidate (cũ trong khi xác thực lại).

Tuy nhiên, khi sử dụng IndexedDB, có nhiều điều quan trọng cần cân nhắc mà có thể không rõ ràng ngay lập tức đối với các nhà phát triển mới sử dụng API. Tài liệu này trả lời các câu hỏi thường gặp và thảo luận về một số điều quan trọng nhất cần lưu ý khi duy trì trạng thái ứng dụng trong IndexedDB.

Giúp ứng dụng của bạn dễ dự đoán

Rất nhiều điểm phức tạp xung quanh IndexedDB bắt nguồn từ việc có quá nhiều yếu tố mà bạn (nhà phát triển) không kiểm soát được. Phần này khám phá nhiều vấn đề bạn phải lưu ý khi làm việc với IndexedDB.

Có thể không ghi được vào bộ nhớ

Lỗi khi ghi vào IndexedDB có thể xảy ra vì nhiều lý do và trong một số trường hợp, những lý do này nằm ngoài tầm kiểm soát của bạn với tư cách là nhà phát triển. Ví dụ: một số trình duyệt không cho phép ghi vào IndexedDB khi ở chế độ duyệt web riêng tư. Cũng có khả năng người dùng đang sử dụng một thiết bị sắp hết dung lượng ổ đĩa và trình duyệt sẽ hạn chế bạn lưu trữ bất cứ nội dung nào.

Do đó, điều quan trọng là bạn phải luôn triển khai quy trình xử lý lỗi thích hợp trong mã IndexedDB. Điều này cũng có nghĩa là bạn nên giữ trạng thái ứng dụng trong bộ nhớ (ngoài việc lưu trữ trạng thái đó) để giao diện người dùng không bị hỏng khi chạy ở chế độ duyệt web riêng tư hoặc khi không có không gian lưu trữ (ngay cả khi một số tính năng khác của ứng dụng yêu cầu bộ nhớ không hoạt động).

Dữ liệu được lưu trữ có thể đã bị người dùng sửa đổi hoặc xoá

Không giống như cơ sở dữ liệu phía máy chủ, nơi bạn có thể hạn chế quyền truy cập trái phép, cơ sở dữ liệu phía máy khách có thể truy cập được vào các tiện ích của trình duyệt và công cụ cho nhà phát triển, và người dùng có thể xoá chúng.

Mặc dù người dùng có thể không thường xuyên sửa đổi dữ liệu được lưu trữ cục bộ, nhưng họ thường xuyên xoá dữ liệu đó. Điều quan trọng là ứng dụng của bạn có thể xử lý cả hai trường hợp này mà không gặp lỗi.

Dữ liệu được lưu trữ có thể đã lỗi thời

Tương tự như phần trước, ngay cả khi người dùng không tự sửa đổi dữ liệu, thì cũng có thể dữ liệu họ có trong bộ nhớ được ghi bằng một phiên bản mã cũ hơn, có thể là một phiên bản có lỗi.

IndexedDB có tính năng hỗ trợ tích hợp sẵn cho các phiên bản giản đồ và nâng cấp bằng phương thức IDBOpenDBRequest.onupgradeneeded(); tuy nhiên, bạn vẫn cần viết mã nâng cấp theo cách có thể xử lý người dùng đến từ phiên bản trước (bao gồm cả phiên bản có lỗi).

Kiểm thử đơn vị có thể rất hữu ích trong trường hợp này, vì thường không thể kiểm thử thủ công tất cả các đường dẫn và trường hợp nâng cấp có thể xảy ra.

Duy trì hiệu suất của ứng dụng

Một trong những tính năng chính của IndexedDB là API không đồng bộ, nhưng đừng để điều đó đánh lừa bạn rằng bạn không cần lo lắng về hiệu suất khi sử dụng. Có một số trường hợp việc sử dụng không đúng cách vẫn có thể chặn luồng chính, dẫn đến tình trạng không phản hồi.

Theo nguyên tắc chung, các thao tác đọc và ghi vào IndexedDB không được lớn hơn mức cần thiết cho dữ liệu đang được truy cập.

Mặc dù IndexedDB cho phép lưu trữ các đối tượng lớn, lồng nhau dưới dạng một bản ghi (và việc này khá thuận tiện theo quan điểm của nhà phát triển), nhưng bạn nên tránh phương pháp này. Lý do là vì khi IndexedDB lưu trữ một đối tượng, trước tiên, nó phải tạo một bản sao có cấu trúc của đối tượng đó và quá trình sao chép có cấu trúc diễn ra trên luồng chính. Đối tượng càng lớn thì thời gian chặn càng dài.

Điều này gây ra một số thách thức khi lập kế hoạch duy trì trạng thái ứng dụng cho IndexedDB, vì hầu hết các thư viện quản lý trạng thái phổ biến (như Redux) đều hoạt động bằng cách quản lý toàn bộ cây trạng thái dưới dạng một đối tượng JavaScript duy nhất.

Mặc dù việc quản lý trạng thái theo cách này mang lại nhiều lợi ích và việc lưu trữ toàn bộ cây trạng thái dưới dạng một bản ghi duy nhất trong IndexedDB có thể rất hấp dẫn và thuận tiện, nhưng việc thực hiện việc này sau mỗi thay đổi (ngay cả khi được điều tiết/gỡ lỗi) sẽ dẫn đến việc chặn không cần thiết cho luồng chính, làm tăng khả năng xảy ra lỗi ghi và trong một số trường hợp, thậm chí còn khiến thẻ trình duyệt gặp sự cố hoặc không phản hồi.

Thay vì lưu trữ toàn bộ cây trạng thái trong một bản ghi, bạn nên chia nhỏ cây trạng thái thành các bản ghi riêng lẻ và chỉ cập nhật những bản ghi thực sự thay đổi.

Cũng như hầu hết các phương pháp hay nhất, đây không phải là quy tắc bắt buộc. Trong trường hợp không thể chia nhỏ đối tượng trạng thái và chỉ ghi tập hợp thay đổi tối thiểu, thì việc chia nhỏ dữ liệu thành các cây con và chỉ ghi các cây con đó vẫn tốt hơn là luôn ghi toàn bộ cây trạng thái. Cải thiện một chút vẫn tốt hơn là không cải thiện gì.

Cuối cùng, bạn phải luôn đo lường tác động đến hiệu suất của mã mà bạn viết. Mặc dù đúng là các lượt ghi nhỏ vào IndexedDB sẽ hoạt động hiệu quả hơn các lượt ghi lớn, nhưng điều này chỉ quan trọng nếu các lượt ghi vào IndexedDB mà ứng dụng của bạn đang thực hiện thực sự dẫn đến các tác vụ cần nhiều thời gian chặn luồng chính và làm giảm trải nghiệm người dùng. Bạn cần phải đo lường để biết mình đang tối ưu hoá cho mục tiêu nào.

Kết luận

Nhà phát triển có thể sử dụng các cơ chế lưu trữ phía máy khách như IndexedDB để cải thiện trải nghiệm người dùng của ứng dụng bằng cách không chỉ duy trì trạng thái trên các phiên mà còn giảm thời gian tải trạng thái ban đầu trong các lượt truy cập lặp lại.

Mặc dù việc sử dụng IndexedDB đúng cách có thể cải thiện đáng kể trải nghiệm người dùng, nhưng việc sử dụng không đúng cách hoặc không xử lý được các trường hợp lỗi có thể dẫn đến ứng dụng bị hỏng và người dùng không hài lòng.

Vì bộ nhớ của ứng dụng khách liên quan đến nhiều yếu tố nằm ngoài tầm kiểm soát của bạn, nên điều quan trọng là mã của bạn phải được kiểm thử kỹ lưỡng và xử lý lỗi đúng cách, ngay cả những lỗi ban đầu có vẻ như không xảy ra.