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 trang web hoặc ứng dụng lần đầu tiên, thường sẽ có một lượng công việc đáng kể liên quan đến việc tạo trạng thái ứng dụng ban đầu dùng để hiển thị 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 đó thực hiện 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 hay để tăng tốc thời gian tải cho các lượt truy cập lặp lại. Sau đó, ứng dụng có thể đồng bộ hoá với bất kỳ dịch vụ API nào ở chế độ 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 lỗi thời 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à nhà phát triển mới sử dụng API có thể chưa nhận ra ngay. Tài liệu này giải đáp các câu hỏi thường gặp và thảo luận 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 vấn đề phức tạp liên quan đến 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 thể kiểm soát. Phần này khám phá nhiều vấn đề mà 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, các 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ó thể 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 kỳ nội dung nào.
Do đó, điều quan trọng là bạn phải luôn triển khai tính năng 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 lưu 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ị gián đoạn khi chạy ở chế độ duyệt web riêng tư hoặc khi không có bộ nhớ (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).
Người dùng có thể đã sửa đổi hoặc xoá dữ liệu được lưu trữ
Không giống như cơ sở dữ liệu phía máy chủ mà bạn có thể hạn chế quyền truy cập trái phép, các tiện ích trình duyệt và công cụ dành cho nhà phát triển có thể truy cập vào cơ sở dữ liệu phía máy khách và người dùng có thể xoá các cơ sở dữ liệu đó.
Mặc dù người dùng thường không sửa đổi dữ liệu được lưu trữ cục bộ, nhưng họ thường 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 đã 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ớ là do một phiên bản mã cũ của bạn ghi, có thể là một phiên bản có lỗi.
IndexedDB có hỗ trợ tích hợp 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 sao cho 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 ở đây, vì thường không thể kiểm thử tất cả các đường dẫn và trường hợp nâng cấp có thể có theo cách thủ công.
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 nghĩ rằng bạn không cần phải lo lắng về hiệu suất khi sử dụng API này. 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, hoạt động đọc và ghi vào IndexedDB không được lớn hơn mức cần thiết đối với 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 duy nhất (và việc này được thừa nhận là khá thuận tiện từ góc độ nhà phát triển), nhưng bạn nên tránh thực hiện phương pháp này. Lý do là vì khi lưu trữ một đối tượng, trước tiên, IndexedDB 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 sẽ diễn ra trên luồng chính. Đối tượng càng lớn thì thời gian chặn càng lâu.
Điều này gây ra một số thách thức khi lập kế hoạch cách duy trì trạng thái ứng dụng vào IndexedDB, vì hầu hết các thư viện quản lý trạng thái phổ biến (như Redux) hoạt động bằng cách quản lý toàn bộ cây trạng thái của bạn 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 có 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ể hấp dẫn và thuận tiện, nhưng việc làm này sau mỗi thay đổi (ngay cả khi bị điều tiết/giảm độ trễ) sẽ dẫn đến việc chặn không cần thiết của 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 cây trạng thái thành các bản ghi riêng lẻ và chỉ cập nhật các bản ghi thực sự thay đổi.
Giống như hầu hết các phương pháp hay nhất, đây không phải là quy tắc tất cả hoặc không. 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, bạn vẫn nên chia nhỏ dữ liệu thành các cây con và chỉ ghi các cây con đó thay vì luôn ghi toàn bộ cây trạng thái. Một chút cải thiện vẫn tốt hơn là không cải thiện gì cả.
Cuối cùng, bạn phải luôn đo lường mức tác động đến hiệu suất của mã bạn viết. Mặc dù việc ghi nhỏ vào IndexedDB sẽ hoạt động hiệu quả hơn so với ghi lớn, nhưng điều này chỉ quan trọng nếu các hoạt động 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ụ dài 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 để hiểu rõ mục tiêu tối ưu hoá của mình.
Kết luận
Nhà phát triển có thể sử dụng các cơ chế lưu trữ ứng dụng như IndexedDB để cải thiện trải nghiệm người dùng của ứng dụng, không chỉ bằng cách duy trì trạng thái trên các phiên mà còn bằng cách giảm thời gian tải trạng thái ban đầu khi người dùng truy cậ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 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 bạn cần kiểm thử kỹ mã và xử lý đúng cách các lỗi, ngay cả những lỗi ban đầu có vẻ như không có khả năng xảy ra.