مرحلة التجربة الأصلية لـfetchLater API

Brendan Kenny
Brendan Kenny

من الشائع أن تحتاج صفحات الويب إلى إرسال البيانات (أو "الإشارات") مرة أخرى إلى خادمها، فكّر في بيانات تحليلية لجلسة المستخدم الحالية، على سبيل المثال. وبالنسبة إلى المطوِّرين، فإن هذا يتطلّب اتخاذ إجراء موازنة: تقليل الطلبات الثابتة، التي قد تكون متكررة، بدون المخاطرة بالبيانات المفقودة في حال إغلاق علامة التبويب أو انتقال المستخدم بعيدًا قبل إرسال المرشد.

يستخدم مطوّرو البرامج عادةً حدثَي pagehide وvisibilitychange لرصد الصفحة أثناء إلغاء تحميلها، ثم يستخدمون navigator.sendBeacon() أو fetch() مع keepalive للإشارة إلى البيانات. ومع ذلك، يحتوي كلا الحدثين على حالات زاوية صعبة تختلف استنادًا إلى متصفّح المستخدم، وأحيانًا لا تصل الأحداث على الإطلاق، خاصةً على الأجهزة الجوّالة.

"fetchLater()" هو اقتراح لاستبدال هذا التعقيد بطلب واحد من واجهة برمجة التطبيقات. وهو يفعل تمامًا كما يوحي اسمها، فهو يطلب من المتصفح التأكد من تقديم طلب في وقت ما في المستقبل، حتى إذا تم إغلاق الصفحة أو انتقال المستخدم بعيدًا عنها.

يمكن استخدام fetchLater() في Chrome لاختباره من خلال مستخدمين حقيقيين يستفيدون من إصدار تجريبي من المصدر اعتبارًا من الإصدار 121 (الذي تم إطلاقه في كانون الثاني (يناير) 2024)، ويستمر حتى 126 Chrome (تموز/يوليو 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});

مثال للاستخدام

عند قياس مؤشرات أداء الويب الأساسية في الحقل، قد تتغيّر مقاييس الأداء إلى أن يغادر المستخدم الصفحة فعليًا. على سبيل المثال، يمكن أن تحدث متغيّرات أكبر في التنسيق في أيّ وقت، أو قد تستغرق الصفحة وقتًا أطول للاستجابة للتفاعل.

ومع ذلك، فأنت لا تريد المخاطرة بفقدان جميع بيانات الأداء بسبب وجود أخطاء أو إشارات غير مكتملة عند إلغاء تحميل الصفحة. إنه مرشح مثالي لـ 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.

مزيد من المعلومات