Веб-страницам часто приходится отправлять данные (или «маяки») обратно на свой сервер — например, аналитические данные для текущего сеанса пользователя. Для разработчиков это требует балансирования: сокращение постоянных, возможно, избыточных запросов без риска потери данных, если вкладка была закрыта или пользователь ушел до того, как можно было отправить маяк.
Традиционно разработчики использовали события 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
, который расширяетoptions
fetch()
с помощью тайм-аута, называемого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 .