Веб-страницам часто приходится отправлять данные (или «маяки») обратно на свой сервер — например, аналитические данные для текущего сеанса пользователя. Для разработчиков это требует балансирования: сокращение постоянных, возможно, избыточных запросов без риска потери данных, если вкладка была закрыта или пользователь ушел до того, как можно было отправить маяк.
Традиционно разработчики использовали события pagehide и visibilitychange , чтобы перехватить страницу при ее выгрузке, а затем использовали navigator.sendBeacon() или fetch() с keepalive для передачи данных маяка. Однако оба этих события имеют сложные ситуации, которые различаются в зависимости от браузера пользователя, а иногда события вообще не происходят, особенно на мобильных устройствах.
fetchLater() — это предложение заменить эту сложность одним вызовом API. Он делает именно то, что следует из названия: он просит браузер убедиться, что запрос сделан в какой-то момент в будущем, даже если страница будет закрыта или пользователь уйдет.
fetchLater() доступен в Chrome для тестирования с реальными пользователями в рамках пробной версии Origin , начиная с версии 121 (выпущенной в январе 2024 г.) и продлится до 3 сентября 2024 г.
API fetchLater()
const fetchLaterResult = fetchLater(request, options);
fetchLater() принимает два аргумента, обычно идентичных аргументам fetch() :
-
request– строковый URL-адрес или экземплярRequest. - Необязательный объект
options, который расширяетoptionsfetch()с помощью тайм-аута, называемогоactivateAfter.
fetchLater() возвращает FetchLaterResult , в настоящее время содержащий только одно свойство activated только для чтения, которому будет присвоено значение true , когда пройдет «позже» и будет выполнена выборка. Любой ответ на запрос fetchLater() отбрасывается.
request
Простейшее использование — это URL-адрес сам по себе:
fetchLater('/endpoint/');
Но, как и в случае fetch() , для запроса fetchLater() можно установить большое количество параметров, включая пользовательские заголовки, поведение учетных данных, тело POST и signal AbortController для потенциальной его отмены .
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
Объект options расширяет параметры fetch() с помощью таймаута activateAfter на тот случай, если вы хотите запустить запрос после таймаута или когда страница будет выгружена, в зависимости от того, что наступит раньше.
Это позволяет вам выбрать компромисс между получением данных в самый последний момент или тогда, когда это более своевременно.
Например, если у вас есть приложение, которое ваши пользователи обычно оставляют открытым в течение всего рабочего дня, вам может потребоваться установить тайм-аут в час, чтобы обеспечить более детальную аналитику, но при этом гарантировать маяк, если пользователь выйдет в любое время до истечения этого часа. Затем можно настроить новый fetchLater() для следующего часа аналитики.
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
Пример использования
Одна из проблем при измерении основных веб-показателей в полевых условиях заключается в том, что любой из показателей производительности может меняться до тех пор, пока пользователь фактически не покинет страницу. Например, большие изменения макета могут произойти в любой момент, или странице может потребоваться еще больше времени, чтобы отреагировать на взаимодействие.
Однако вы не хотите рисковать потерей всех данных о производительности из-за ошибок или неполного сигнала при выгрузке страницы. Это идеальный кандидат для fetchLater() .
В этом примере библиотека web-vitals.js используется для мониторинга показателей, а fetchLater() используется для передачи результатов в конечную точку аналитики:
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);
Каждый раз, когда поступает обновление метрики, любой существующий запланированный fetchLater() отменяется с помощью AbortController , и создается новый fetchLater() с включенным обновлением.
Попробуйте fetchLater()
Как уже говорилось, fetchLater() доступна в пробной версии Origin до версии Chrome 126. Дополнительную информацию о пробных версиях Origin см. в разделе «Начало работы с пробными версиями Origin».
Для локального тестирования fetchLater можно включить с помощью флага функций экспериментальной веб-платформы по адресу chrome://flags/#enable-experimental-web-platform-features . Его также можно включить, запустив Chrome из командной строки с помощью --enable-experimental-web-platform-features или более целевого флага --enable-features=FetchLaterAPI .
Если вы используете его на общедоступной странице, обязательно определите функцию, проверив, определен ли глобальный fetchLater перед его использованием:
if (globalThis.fetchLater) {
// Set up beaconing using fetchLater().
// ...
}
Обратная связь
Отзывы разработчиков необходимы для правильного создания новых веб-API, поэтому , пожалуйста, сообщайте о проблемах и отзывах на GitHub .