Cải thiện tính năng loại bỏ trang trong XMLHttpRequest() đồng bộ

Giảm tình trạng điều hướng bị trễ

Joe Medley
Joe Medley

Thông thường, một trang hoặc ứng dụng sẽ có dữ liệu phân tích hoặc dữ liệu khác chưa được gửi tại thời điểm người dùng đóng trang hoặc ứng dụng đó. Để ngăn mất dữ liệu, một số trang web sử dụng lệnh gọi đồng bộ đến XMLHttpRequest() để giữ cho trang hoặc ứng dụng mở cho đến khi dữ liệu của trang hoặc ứng dụng đó được truyền đến máy chủ. Không chỉ có những cách tốt hơn để lưu dữ liệu, mà kỹ thuật này còn tạo ra trải nghiệm người dùng kém bằng cách trì hoãn việc đóng trang lên đến vài giây.

Chúng ta cần thay đổi phương pháp này và các trình duyệt đang phản hồi. Quy cách XMLHttpRequest() đã được lên kế hoạch ngừng sử dụng và xoá. Chrome 80 thực hiện bước đầu tiên bằng cách không cho phép các lệnh gọi đồng bộ bên trong một số trình xử lý sự kiện, cụ thể là beforeunload, unload, pagehidevisibilitychange khi các lệnh gọi này được kích hoạt trong thao tác đóng. Gần đây, WebKit cũng đã phát hành một cam kết triển khai cùng một thay đổi về hành vi.

Trong bài viết này, tôi sẽ mô tả ngắn gọn các lựa chọn dành cho những người cần thời gian để cập nhật trang web và trình bày các giải pháp thay thế cho XMLHttpRequest().

Chọn không tham gia tạm thời

Chrome không chỉ muốn rút phích cắm trên XMLHttpRequest(), đó là lý do có một số lựa chọn chọn không tham gia tạm thời. Đối với các trang web trên Internet, bạn có thể dùng thử tính năng phân phát theo nguồn gốc. Với cách này, bạn thêm một mã thông báo dành riêng cho nguồn gốc vào tiêu đề trang để bật các lệnh gọi XMLHttpRequest() đồng bộ. Lựa chọn này sẽ kết thúc ngay trước khi Chrome 89 được phát hành, vào khoảng tháng 3 năm 2021. Khách hàng Chrome Enterprise cũng có thể sử dụng cờ chính sách AllowSyncXHRInPageDismissal. Cờ này cũng sẽ kết thúc cùng lúc.

Phương án thay thế

Bất kể bạn gửi dữ liệu về máy chủ theo cách nào, tốt nhất bạn nên tránh đợi cho đến khi trang tải xuống để gửi tất cả dữ liệu cùng một lúc. Ngoài việc tạo trải nghiệm người dùng không tốt, tính năng huỷ tải không đáng tin cậy trên các trình duyệt hiện đại và có nguy cơ mất dữ liệu nếu có sự cố. Cụ thể, sự kiện huỷ tải thường không kích hoạt trên trình duyệt di động vì có nhiều cách để đóng một thẻ hoặc trình duyệt trên hệ điều hành di động mà không kích hoạt sự kiện unload. Với XMLHttpRequest(), bạn có thể chọn sử dụng tải trọng nhỏ. Giờ đây, đây là yêu cầu bắt buộc. Cả hai phương án thay thế đều có giới hạn tải lên là 64 KB cho mỗi ngữ cảnh, như yêu cầu của quy cách.

Tìm nạp keepalive

Fetch API (API Tìm nạp) cung cấp một phương thức mạnh mẽ để xử lý các hoạt động tương tác với máy chủ và một giao diện nhất quán để sử dụng trên nhiều API nền tảng. Trong số các tuỳ chọn của nó có keepalive, giúp đảm bảo rằng một yêu cầu tiếp tục cho dù trang đã tạo yêu cầu đó có mở hay không:

window.addEventListener('unload', {
  fetch
('/siteAnalytics', {
    method
: 'POST',
    body
: getStatistics(),
    keepalive
: true
 
});
}

Phương thức fetch() có ưu điểm là kiểm soát tốt hơn nội dung được gửi đến máy chủ. Điều tôi không thể hiện trong ví dụ là fetch() cũng trả về một lời hứa phân giải bằng đối tượng Response. Vì đang cố gắng thoát khỏi quá trình tải xuống của trang, nên tôi chọn không làm gì với trang đó.

SendBeacon()

SendBeacon() thực sự sử dụng API Tìm nạp, đó là lý do tại sao API này có cùng giới hạn tải trọng 64 KB và cũng là lý do đảm bảo rằng yêu cầu sẽ tiếp tục sau khi tải trang xuống. Ưu điểm chính của phương thức này là tính đơn giản. API này cho phép bạn gửi dữ liệu bằng một dòng mã duy nhất:

window.addEventListener('unload', {
  navigator
.sendBeacon('/siteAnalytics', getStatistics());
}

Kết luận

Khi fetch() ngày càng có sẵn trên các trình duyệt, XMLHttpRequest() hy vọng sẽ bị xoá khỏi nền tảng web vào một thời điểm nào đó. Các nhà cung cấp trình duyệt đồng ý rằng cần phải xoá cookie này, nhưng sẽ mất thời gian. Việc ngừng sử dụng một trong những trường hợp sử dụng tệ nhất là bước đầu tiên giúp cải thiện trải nghiệm người dùng cho mọi người.

Ảnh chụp của Matthew Hamilton trên Unsplash