مزامنة خلفية مربع العمل

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

واجهة BackgroundSync API الجديدة هو الحل المثالي لهذه المشكلة. عندما يكتشف عامل خدمة تعذّر طلب الشبكة، يمكن التسجيل لتلقي حدث sync، يتم تسليمه عندما يعتقد المتصفح أن الاتصال قد عاد. لاحظ أنه يمكن تسليم حدث المزامنة حتى إذا غادر المستخدم تطبيقه، مما يجعلها أكثر فعالية بكثير من الطريقة التقليدية إعادة محاولة الطلبات التي أخفقت.

تم تصميم أداة Workbox Background Sync لتسهيل استخدام واجهة برمجة التطبيقات BackgroundSync API ودمجها مع وحدات Workbox الأخرى. أُنشأها جون هنتر، الذي كان متخصصًا أيضًا تنفيذ استراتيجية احتياطية للمتصفّحات التي لم تطبّق مزامنة الخلفية

تعذَّرت إعادة تشغيل المتصفّحات التي تتيح استخدام واجهة BackgroundSync API تلقائيًا. نيابةً عنك على الفاصل الزمني يديره المتصفِّح من المرجّح أن يتم استخدام خوارزمية الرقود الأسي بين محاولات إعادة التشغيل. في المتصفحات التي لا تتوافق مع واجهة برمجة تطبيقات BackgroundSync API في الأصل، فستقوم أداة Workbox Background Sync محاولة إعادة تشغيل تلقائيًا كلما تم بدء تشغيل عامل الخدمة.

الاستخدام الأساسي

أسهل طريقة لاستخدام ميزة "مزامنة الخلفية" هي استخدام Plugin الذي إضافة الطلبات التي تعذّر تنفيذها تلقائيًا إلى قائمة الانتظار وإعادة المحاولة عند sync يتم تنشيط الأحداث.

import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
  maxRetentionTime: 24 * 60, // Retry for max of 24 Hours (specified in minutes)
});

registerRoute(
  /\/api\/.*\/*.json/,
  new NetworkOnly({
    plugins: [bgSyncPlugin],
  }),
  'POST'
);

انضمام "BackgroundSyncPlugin" إلى الكرة fetchDidFail معاودة الاتصال بالمكون الإضافي، لا يتم استدعاء fetchDidFail إلا في حال وجود استثناء، وذلك على الأرجح بسبب إلى تعطُّل الشبكة. وهذا يعني أنّه لن تتم إعادة محاولة معالجة الطلبات إذا كانت هناك تم تلقي الرد حالة الخطأ 4xx أو 5xx. إذا أردت إعادة محاولة تنفيذ كل الطلبات التي تؤدي إلى ظهور حالة 5xx مثلاً، يمكنك القيام بذلك عن طريق إضافة المكون الإضافي fetchDidSucceed على استراتيجيتك:

const statusPlugin = {
  fetchDidSucceed: ({response}) => {
    if (response.status >= 500) {
      // Throwing anything here will trigger fetchDidFail.
      throw new Error('Server error.');
    }
    // If it's not 5xx, use the response as-is.
    return response;
  },
};

// Add statusPlugin to the plugins array in your strategy.

الاستخدام المتقدّم

توفّر أيضًا Workbox Background Sync أيضًا فئة Queue، التي يمكنك لإنشاء مثيل وإضافة الطلبات التي أخفقت إلى. يتم تخزين الطلبات التي تعذّر تنفيذها في IndexedDB وتتم إعادة المحاولة عندما يعتقد المتصفح أنه قد تمت استعادة الاتصال (أي عند استلام حدث المزامنة).

إنشاء قائمة انتظار

يجب إنشاء قائمة انتظار مزامنة خلفية لصندوق العمل باستخدام اسم قائمة انتظار (والذي يجب أن يكون فريدًا المصدر):

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

يُستخدم اسم قائمة الانتظار كجزء من اسم العلامة التي تحصل register() بواسطة العالم SyncManager من المهم يُستخدم أيضًا باعتباره Object Store لـ قاعدة بيانات IndexedDB.

إضافة طلب إلى قائمة الانتظار

بعد إنشاء مثيل قائمة الانتظار، يمكنك إضافة الطلبات التي أخفقت إليها. أضفت الطلب الذي تعذّر تنفيذه من خلال استدعاء طريقة .pushRequest(). على سبيل المثال: ترصد التعليمة البرمجية التالية أي طلبات أخفقت وتضيفها إلى قائمة الانتظار:

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

self.addEventListener('fetch', event => {
  // Add in your own criteria here to return early if this
  // isn't a request that should use background sync.
  if (event.request.method !== 'POST') {
    return;
  }

  const bgSyncLogic = async () => {
    try {
      const response = await fetch(event.request.clone());
      return response;
    } catch (error) {
      await queue.pushRequest({request: event.request});
      return error;
    }
  };

  event.respondWith(bgSyncLogic());
});

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

اختبار المزامنة في الخلفية في Workbox

للأسف، كان اختبار BackgroundSync غير واضح وصعب إلى حد ما لعدة أسباب.

أفضل طريقة لاختبار عملية التنفيذ هي اتّباع الخطوات التالية:

  1. حمِّل صفحة وسجِّل مشغّل الخدمات.
  2. أوقِف شبكة جهاز الكمبيوتر أو أوقِف خادم الويب.
    • لا تستخدم أدوات Chrome DEVTOOL بلا إنترنت. مربع الاختيار بلا اتصال في لا تؤثر "أدوات مطوري البرامج" إلا في الطلبات الواردة من الصفحة. طلبات مشغّل الخدمات الاستمرار في المضي قدمًا.
  3. أدخِل طلبات الشبكة التي يجب وضعها في قائمة الانتظار باستخدام Workbox Background Sync.
    • يمكنك التحقق من وضع الطلبات في قائمة الانتظار من خلال مراجعة Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
  4. الآن فعِّل الشبكة أو خادم الويب.
  5. فرض حدث sync مبكر من خلال الانتقال إلى Chrome DevTools > Application > Service Workers، مع إدخال اسم العلامة workbox-background-sync:<your queue name> حيث يجب أن يكون <your queue name> اسم قائمة الانتظار التي قمت بتعيينها، ثم النقر فوق "مزامنة" .

    مثال على زر المزامنة في &quot;أدوات مطوري البرامج في Chrome&quot;

  6. سترى طلبات الشبكة تمرّ عبر الطلبات التي تعذّر تنفيذها من المفترض أن تكون بيانات IndexedDB فارغة نظرًا لأن الطلبات قد تمت تمت إعادة التشغيل بنجاح.

الأنواع

BackgroundSyncPlugin

صف ينفّذ معاودة الاتصال لمراحل نشاط fetchDidFail. هذا يجعل من كانت إضافة الطلبات التي أخفقت إلى قائمة انتظار المزامنة في الخلفية أسهل.

أماكن إقامة

Queue

فئة لإدارة عملية تخزين الطلبات التي تعذّر تنفيذها في IndexedDB وإعادة المحاولة لاحقًا. يمكن مراقبة جميع أجزاء عملية التخزين وإعادة التشغيل عبر مع معاودة الاتصال.

أماكن إقامة

  • الدالة الإنشائية

    فراغ

    يتم إنشاء مثيل لقائمة الانتظار بالخيارات المحددة

    تبدو دالة constructor كما يلي:

    (name: string, options?: QueueOptions) => {...}

    • الاسم

      سلسلة

      الاسم الفريد لقائمة الانتظار هذه. يجب أن يكون هذا الاسم فريدة لأنها تُستخدم لتسجيل أحداث المزامنة وطلبات التخزين في IndexedDB الخاص بهذا المثيل. سيحدث خطأ إذا تم اكتشاف اسم مكرر.

    • الخيارات

      QueueOptions اختيارية

  • الاسم

    سلسلة

  • getAll

    فراغ

    تعرض جميع الإدخالات التي لم تنتهِ صلاحيتها (لكل maxRetentionTime). وتتم إزالة أي إدخالات منتهية الصلاحية من قائمة الانتظار.

    تبدو دالة getAll كما يلي:

    () => {...}

    • returns

      Promise&lt;QueueEntry[]&gt;

  • popRequest

    فراغ

    إزالة وإعادة الطلب الأخير في قائمة الانتظار (بالإضافة إلى الطابع الزمني وأي بيانات وصفية). يظهر العنصر المعروض على النحو التالي: {request, timestamp, metadata}

    تبدو دالة popRequest كما يلي:

    () => {...}

    • returns

      Promise&lt;QueueEntry&gt;

  • pushRequest

    فراغ

    تخزين الطلب الذي تم تمريره في IndexedDB (مع طابعه الزمني وأي بيانات التعريف) في نهاية قائمة الانتظار.

    تبدو دالة pushRequest كما يلي:

    (entry: QueueEntry) => {...}

    • الإدخال

      QueueEntry

    • returns

      وعود <باطلة>

  • registerSync

    فراغ

    يتم تسجيل حدث مزامنة باستخدام علامة فريدة لهذا المثيل.

    تبدو دالة registerSync كما يلي:

    () => {...}

    • returns

      وعود <باطلة>

  • replayRequests

    فراغ

    تكرار كل طلب في قائمة الانتظار مع محاولة استرجاعه في حالة إخفاق أي طلب في إعادة جلبه، يتم إعادته إلى الموضع نفسه في قائمة الانتظار (التي تسجّل إعادة محاولة لحدث المزامنة التالي).

    تبدو دالة replayRequests كما يلي:

    () => {...}

    • returns

      وعود <باطلة>

  • shiftRequest

    فراغ

    إزالة الطلب الأول في قائمة الانتظار وإرجاعه (بالإضافة إلى الطابع الزمني وأي بيانات وصفية). يظهر العنصر المعروض على النحو التالي: {request, timestamp, metadata}

    تبدو دالة shiftRequest كما يلي:

    () => {...}

    • returns

      Promise&lt;QueueEntry&gt;

  • الحجم

    فراغ

    تعرض عدد الإدخالات المتوفّرة في قائمة الانتظار. يُرجى العلم أنّ الإدخالات المنتهية الصلاحية (لكل maxRetentionTime) يتم تضمينها أيضًا في هذا العدد.

    تبدو دالة size كما يلي:

    () => {...}

    • returns

      Promise&lt;number&gt;

  • unshiftRequest

    فراغ

    تخزين الطلب الذي تم تمريره في IndexedDB (مع طابعه الزمني وأي بيانات التعريف) في بداية قائمة الانتظار.

    تبدو دالة unshiftRequest كما يلي:

    (entry: QueueEntry) => {...}

    • الإدخال

      QueueEntry

    • returns

      وعود <باطلة>

QueueOptions

أماكن إقامة

  • forceSyncFallback

    قيمة منطقية اختيارية

  • maxRetentionTime

    الرقم اختياري

  • onSync

    OnSyncCallback اختياري

QueueStore

هي فئة لإدارة طلبات التخزين من قائمة انتظار في IndexedDB، الفهرسة حسب اسم قائمة الانتظار للوصول إليها بسهولة أكبر.

لن يحتاج معظم المطوّرين إلى الوصول إلى هذه الفئة مباشرةً. يتعرض لحالات الاستخدام المتقدمة.

أماكن إقامة

  • الدالة الإنشائية

    فراغ

    يتم ربط هذا المثيل بمثيل قائمة الانتظار، بحيث يمكن المحددة باسم قائمة الانتظار.

    تبدو دالة constructor كما يلي:

    (queueName: string) => {...}

    • queueName

      سلسلة

  • deleteEntry

    فراغ

    يؤدي هذا الإجراء إلى حذف إدخال المعرّف المحدّد.

    تحذير: لا تضمن هذه الطريقة أن ينتمي الإدخال المحذوف إلى هذا قائمة انتظار (أي تطابق queueName) لكن هذا القيد مقبول لأنّ هذه الفئة غير علنية. سيؤدي فحص إضافي إلى هذه الطريقة أبطأ مما ينبغي.

    تبدو دالة deleteEntry كما يلي:

    (id: number) => {...}

    • id

      الرقم

    • returns

      وعود <باطلة>

  • getAll

    فراغ

    إرجاع جميع الإدخالات في المتجر المطابقة لـ queueName.

    تبدو دالة getAll كما يلي:

    () => {...}

    • returns

      Promise&lt;QueueStoreEntry[]&gt;

  • popEntry

    فراغ

    لإزالة الإدخال الأخير وإعادة إدخاله في قائمة الانتظار المطابقة مع queueName.

    تبدو دالة popEntry كما يلي:

    () => {...}

    • returns

      Promise&lt;QueueStoreEntry&gt;

  • pushEntry

    فراغ

    يمكنك إلحاق آخر إدخال في قائمة الانتظار.

    تبدو دالة pushEntry كما يلي:

    (entry: UnidentifiedQueueStoreEntry) => {...}

    • الإدخال

      UnidentifiedQueueStoreEntry

    • returns

      وعود <باطلة>

  • shiftEntry

    فراغ

    لإزالة الإدخال الأول في قائمة الانتظار المطابقة مع queueName وعرضه.

    تبدو دالة shiftEntry كما يلي:

    () => {...}

    • returns

      Promise&lt;QueueStoreEntry&gt;

  • الحجم

    فراغ

    تعرض عدد الإدخالات في المتجر المطابقة لـ queueName.

    تبدو دالة size كما يلي:

    () => {...}

    • returns

      Promise&lt;number&gt;

  • unshiftEntry

    فراغ

    يُرجى إضافة الإدخال أولاً في قائمة الانتظار.

    تبدو دالة unshiftEntry كما يلي:

    (entry: UnidentifiedQueueStoreEntry) => {...}

    • الإدخال

      UnidentifiedQueueStoreEntry

    • returns

      وعود <باطلة>

StorableRequest

يشير ذلك المصطلح إلى فئة لتسهيل ترتيب الطلبات وإلغاء تسلسلها. يمكن تخزينها في IndexedDB.

لن يحتاج معظم المطوّرين إلى الوصول إلى هذه الفئة مباشرةً. يتعرض لحالات الاستخدام المتقدمة.

أماكن إقامة

  • الدالة الإنشائية

    فراغ

    تقبل كائن بيانات الطلب الذي يمكن استخدامه لإنشاء Request ولكن يمكن أيضًا تخزينها في IndexedDB.

    تبدو دالة constructor كما يلي:

    (requestData: RequestData) => {...}

    • requestData

      RequestData

      كائن بيانات الطلب الذي يتضمن url بالإضافة إلى أي خصائص ذات صلة بـ [requestInit]https://fetch.spec.whatwg.org/#requestinit

  • استنساخ

    فراغ

    تنشئ نسخة طبق الأصل من المثيل وتعرضها بشكل عميق.

    تبدو دالة clone كما يلي:

    () => {...}

  • toObject

    فراغ

    لعرض نسخة طبق الأصل من عنصر _requestData للمثيلات.

    تبدو دالة toObject كما يلي:

    () => {...}

    • returns

      RequestData

  • toRequest

    فراغ

    تحويل هذا المثيل إلى طلب.

    تبدو دالة toRequest كما يلي:

    () => {...}

    • returns

      الطلب

  • fromRequest

    فراغ

    تحويل كائن طلب إلى كائن عادي يمكن تنظيمه استنساخ أو مزود بسلاسل JSON.

    تبدو دالة fromRequest كما يلي:

    (request: Request) => {...}

    • طلب

      الطلب