من الشائع أن تحتاج صفحات الويب إلى إرسال البيانات (أو "الإشارة") مرة أخرى إلى خادمها، مثل بيانات الإحصاءات لجلسة المستخدِم الحالية. بالنسبة إلى المطوّرين، يتطلّب ذلك موازنة بين خفض الطلبات المستمرة والمتكرّرة في بعض الأحيان بدون المخاطرة بفقدان البيانات في حال إغلاق علامة التبويب أو انتقال المستخدم إلى صفحة أخرى قبل إرسال إشارة.
في العادة، كان المطوّرون يستخدِمون حدثَي pagehide
وvisibilitychange
لرصد الصفحة أثناء تفريغها، ثم يستخدِمون navigator.sendBeacon()
أو fetch()
مع keepalive
لعرض بيانات ال beacon. ومع ذلك، يتضمّن كلا الحدثَين حالات صعبة تختلف حسب متصفّح المستخدِم، وفي بعض الأحيان لا تصل الأحداث مطلقًا، خاصةً على الأجهزة الجوّالة.
fetchLater()
هو اقتراح لاستبدال هذه التعقيدات بطلب بيانات واحد من واجهة برمجة التطبيقات. ويعمل هذا الإجراء على النحو الذي يوحي به اسمه تمامًا: فهو يطلب من المتصفّح التأكّد من إرسال طلب في وقت ما في المستقبل، حتى إذا تم إغلاق الصفحة أو غادر المستخدم الصفحة.
تتوفّر fetchLater()
في Chrome للاختبار مع مستخدمين حقيقيين في إطار مرحلة التجربة والتقييم بدءًا من الإصدار 121 (الذي تم إصداره في كانون الثاني (يناير) 2024)، وتستمر حتى 3 أيلول (سبتمبر) 2024.
واجهة برمجة التطبيقات 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
وAbortController
signal
لإلغائه.
fetchLater('/endpoint/', {
method: 'GET',
cache: 'no-store',
mode: 'same-origin',
headers: {Authorization: 'SUPER_SECRET'},
});
options
يُوسّع عنصر الخيارات خيارات fetch()
باستخدام مهلة، activateAfter
، في حال أردت تشغيل الطلب بعد المهلة أو عند إزالة تحميل الصفحة، أيهما أقرب.
يتيح لك ذلك تحديد المفاضلة بين الحصول على البيانات في آخر لحظة ممكنة أو عندما تكون في الوقت المناسب.
على سبيل المثال، إذا كان لديك تطبيق يتركه المستخدمون عادةً مفتوحًا طوال يوم العمل، قد تحتاج إلى ضبط مهلة مدتها ساعة لضمان إحصاءات أكثر دقة مع ضمان إرسال إشارات إذا خرج المستخدم في أي وقت قبل انقضاء هذه الساعة. يمكن بعد ذلك إعداد fetchLater()
جديد للساعة التالية من الإحصاءات.
const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});
مثال على الاستخدام
من المشاكل التي تواجهك عند قياس مؤشرات أداء الويب الأساسية في الميدان أنّ أيًا من مقاييس الأداء قد يتغيّر إلى أن يغادر المستخدم الصفحة فعليًا. على سبيل المثال، يمكن أن تحدث تغييرات أكبر في التصميم في أي وقت، أو يمكن أن تستغرق الصفحة وقتًا أطول للردّ على تفاعل.
ومع ذلك، لا تريد المخاطرة بفقدان جميع بيانات الأداء بسبب إشارات Beacon غير المكتملة أو التي تتضمّن أخطاء عند إزالة الصفحة من الذاكرة. وهو مرشح مثالي لـ 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()
في مرحلة تجربة وتقييم حتى الإصدار 126 من Chrome. اطّلِع على مقالة البدء في استخدام تجارب المصدر للحصول على معلومات أساسية عن تجارب المصدر.
للاختبار على الجهاز، يمكن تفعيل 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().
// ...
}
ملاحظات
إنّ ملاحظات المطوّرين ضرورية لتحسين واجهات برمجة تطبيقات الويب الجديدة، لذا يُرجى الإبلاغ عن المشاكل والملاحظات على GitHub.