Thông thường, các trang web cần gửi dữ liệu (hoặc "beacon") trở lại máy chủ của chúng, chẳng hạn như dữ liệu phân tích cho phiên hiện tại của người dùng. Đối với nhà phát triển, việc này đòi hỏi phải cân bằng: giảm các yêu cầu liên tục, có thể dư thừa mà không gây rủi ro bỏ lỡ dữ liệu nếu thẻ đã đóng hoặc người dùng đã rời khỏi trước khi có thể gửi beacon.
Thông thường, các nhà phát triển thường sử dụng các sự kiện pagehide
và visibilitychange
để bắt trang khi trang đó bị tải, sau đó sử dụng navigator.sendBeacon()
hoặc fetch()
với keepalive
để báo hiệu dữ liệu. Tuy nhiên, cả hai sự kiện này đều có các trường hợp khó xử khác nhau tuỳ theo trình duyệt của người dùng và đôi khi các sự kiện này không bao giờ xuất hiện, đặc biệt là trên thiết bị di động.
fetchLater()
là một đề xuất thay thế sự phức tạp này bằng một lệnh gọi API duy nhất. Phương thức này hoạt động đúng như tên gọi: yêu cầu trình duyệt đảm bảo rằng một yêu cầu được thực hiện vào một thời điểm nào đó trong tương lai, ngay cả khi trang bị đóng hoặc người dùng rời khỏi trang.
fetchLater()
có trong Chrome để thử nghiệm với người dùng thực tế trong một thử nghiệm về nguồn gốc bắt đầu từ phiên bản 121 (phát hành vào tháng 1 năm 2024) và kéo dài đến ngày 3 tháng 9 năm 2024.
API fetchLater()
const fetchLaterResult = fetchLater(request, options);
fetchLater()
nhận hai đối số, thường giống với các đối số của fetch()
:
request
, một URL chuỗi hoặc một thực thểRequest
.- Một đối tượng
options
không bắt buộc, giúp mở rộngoptions
từfetch()
với thời gian chờ có tên làactivateAfter
.
fetchLater()
trả về một FetchLaterResult
, hiện chỉ chứa một thuộc tính chỉ có thể đọc activated
. Thuộc tính này sẽ được thiết lập thành true
khi quá trình " sau" truyền và tìm nạp đã được thực hiện. Mọi phản hồi đối với yêu cầu fetchLater()
sẽ bị loại bỏ.
request
Cách sử dụng đơn giản nhất là một URL:
fetchLater('/endpoint/');
Tuy nhiên, giống như fetch()
, bạn có thể đặt nhiều tuỳ chọn trên yêu cầu fetchLater()
, bao gồm cả tiêu đề tuỳ chỉnh, hành vi thông tin xác thực, nội dung POST
và AbortController
signal
để có thể huỷ yêu cầu đó.
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
Đối tượng tuỳ chọn mở rộng các tuỳ chọn của fetch()
bằng một thời gian chờ, activateAfter
, trong trường hợp bạn muốn kích hoạt yêu cầu sau thời gian chờ hoặc khi trang được tải xuống, tuỳ theo điều kiện nào đến trước.
Điều này cho phép bạn quyết định đánh đổi giữa việc nhận dữ liệu vào thời điểm cuối cùng có thể hoặc khi dữ liệu kịp thời hơn.
Ví dụ: nếu người dùng thường mở một ứng dụng trong suốt ngày làm việc, thì bạn nên đặt thời gian chờ là một giờ để đảm bảo có được dữ liệu phân tích chi tiết hơn, đồng thời vẫn đảm bảo có beacon nếu người dùng thoát ứng dụng bất cứ lúc nào trước khi hết thời gian chờ đó. Sau đó, bạn có thể thiết lập một fetchLater()
mới cho dữ liệu phân tích trong giờ tiếp theo.
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
Ví dụ về cách sử dụng
Một vấn đề khi đo lường Chỉ số quan trọng chính của trang web trong trường là bất kỳ chỉ số nào về hiệu suất đều có thể thay đổi cho đến khi người dùng thực sự rời khỏi trang. Ví dụ: các thay đổi bố cục lớn hơn có thể xảy ra bất cứ lúc nào hoặc trang có thể mất nhiều thời gian hơn để phản hồi một lượt tương tác.
Tuy nhiên, bạn không muốn có nguy cơ mất tất cả dữ liệu hiệu suất do bị lỗi hoặc báo hiệu chưa hoàn tất khi tải trang. Đây là một ứng cử viên hoàn hảo cho fetchLater()
.
Trong ví dụ này, thư viện web-vitals.js được dùng để theo dõi các chỉ số và fetchLater()
được dùng để báo cáo kết quả đến một điểm cuối phân tích:
import {onCLS, onINP, onLCP} from 'web-vitals';
const queue = new Set();
let fetchLaterController;
let fetchLaterResult;
function updateQueue(metricUpdate) {
// If there was an already complete request for whatever
// reason, clear out the queue of already-sent updates.
if (fetchLaterResult?.activated) {
queue.clear();
}
queue.add(metricUpdate);
// JSON.stringify used here for simplicity and will likely include
// more data than you need. Replace with a preferred serialization.
const body = JSON.stringify([...queue]);
// Abort any existing `fetchLater()` and schedule a new one with
// the update included.
fetchLaterController?.abort();
fetchLaterController = new AbortController();
fetchLaterResult = fetchLater('/analytics', {
method: 'POST',
body,
signal: fetchLaterController.signal,
activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
});
}
onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);
Mỗi khi có thông tin cập nhật về chỉ số, mọi fetchLater()
theo lịch hiện có sẽ bị huỷ bằng AbortController
và một fetchLater()
mới sẽ được tạo cùng với thông tin cập nhật.
Dùng thử fetchLater()
Như đã nêu, fetchLater()
có trong bản dùng thử theo nguyên gốc cho đến Chrome 126. Hãy xem bài viết "Bắt đầu dùng thử phiên bản gốc" để biết thông tin cơ bản về phiên bản gốc
Để kiểm thử cục bộ, bạn có thể bật fetchLater
bằng cờ tính năng Nền tảng web thử nghiệm tại chrome://flags/#enable-experimental-web-platform-features
. Bạn cũng có thể bật tính năng này bằng cách chạy Chrome từ dòng lệnh bằng --enable-experimental-web-platform-features
hoặc cờ --enable-features=FetchLaterAPI
được nhắm mục tiêu cụ thể.
Nếu bạn sử dụng tính năng này trên một trang công khai, hãy nhớ phát hiện tính năng bằng cách kiểm tra xem fetchLater
toàn cục có được xác định hay không trước khi sử dụng:
if (globalThis.fetchLater) {
// Set up beaconing using fetchLater().
// ...
}
Phản hồi
Ý kiến phản hồi của nhà phát triển là yếu tố thiết yếu để xây dựng API web mới đúng cách. Vì vậy, vui lòng gửi vấn đề và ý kiến phản hồi trên GitHub.