جعبه کار-پس زمینه-همگام سازی

هنگامی که داده ها را به یک وب سرور ارسال می کنید، گاهی اوقات درخواست ها با شکست مواجه می شوند. ممکن است به این دلیل باشد که کاربر اتصال خود را از دست داده است، یا ممکن است به دلیل از کار افتادن سرور باشد. در هر صورت اغلب می خواهید درخواست ها را بعداً دوباره ارسال کنید.

BackgroundSync API جدید یک راه حل ایده آل برای این مشکل است. هنگامی که یک سرویس‌دهنده تشخیص می‌دهد که درخواست شبکه ناموفق بوده است، می‌تواند برای دریافت یک رویداد sync ثبت‌نام کند، که وقتی مرورگر فکر می‌کند اتصال بازگشته است، تحویل داده می‌شود. توجه داشته باشید که رویداد همگام‌سازی را می‌توان حتی در صورتی که کاربر برنامه را ترک کرده باشد ، تحویل داد، که آن را بسیار مؤثرتر از روش سنتی امتحان مجدد درخواست‌های ناموفق می‌کند.

Workbox Background Sync برای سهولت استفاده از BackgroundSync API و ادغام استفاده از آن با سایر ماژول های Workbox طراحی شده است. همچنین یک استراتژی بازگشتی برای مرورگرهایی که هنوز BackgroundSync را پیاده سازی نکرده اند، پیاده سازی می کند.

مرورگرهایی که از 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 ذخیره می‌شوند و زمانی که مرورگر فکر می‌کند اتصال بازیابی شده است (یعنی زمانی که رویداد همگام‌سازی را دریافت می‌کند) دوباره امتحان می‌شوند.

ایجاد صف

برای ایجاد صف همگام‌سازی پس‌زمینه Workbox، باید آن را با نام صف بسازید (که باید منحصر به فرد باشد):

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

const queue = new Queue('myQueueName');

نام صف به عنوان بخشی از نام تگ استفاده می شود که register() -ed توسط SyncManager جهانی دریافت می کند. همچنین به عنوان نام Object Store برای پایگاه داده IndexedDB استفاده می شود.

افزودن یک درخواست به صف

هنگامی که نمونه Queue خود را ایجاد کردید، می توانید درخواست های ناموفق را به آن اضافه کنید. شما درخواست ناموفق را با فراخوانی متد .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 DEVTOOLS آفلاین استفاده نکنید. چک باکس آفلاین در DevTools فقط بر درخواست‌های صفحه تأثیر می‌گذارد. درخواست‌های کارکنان خدمات ادامه خواهد یافت.
  3. درخواست های شبکه ای را ایجاد کنید که باید با Workbox Background Sync در صف قرار گیرند.
    • می‌توانید با جستجو در Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests بررسی کنید که درخواست‌ها در صف قرار گرفته‌اند.
  4. حالا شبکه یا وب سرور خود را روشن کنید.
  5. با رفتن به Chrome DevTools > Application > Service Workers ، یک رویداد sync اولیه را اجباری کنید، نام برچسب workbox-background-sync:<your queue name> که در آن <your queue name> باید نام صفی باشد که تنظیم کرده‌اید، و سپس با کلیک بر روی دکمه "همگام سازی".

    نمونه‌ای از دکمه همگام‌سازی در Chrome DevTools

  6. باید مشاهده کنید که درخواست‌های شبکه برای درخواست‌های ناموفق انجام می‌شوند و داده‌های IndexedDB اکنون باید خالی باشند زیرا درخواست‌ها با موفقیت دوباره پخش شده‌اند.

انواع

BackgroundSyncPlugin

کلاسی که بازگشت به تماس چرخه حیات fetchDidFail را اجرا می کند. این کار اضافه کردن درخواست های ناموفق را به صف همگام سازی پس زمینه آسان تر می کند.

خواص

Queue

کلاسی برای مدیریت ذخیره درخواست های ناموفق در IndexedDB و امتحان مجدد آنها بعدا. تمام بخش‌های فرآیند ذخیره‌سازی و پخش مجدد از طریق callback قابل مشاهده است.

خواص

  • سازنده

    خالی

    با گزینه های داده شده یک نمونه از Queue ایجاد می کند

    تابع constructor به نظر می رسد:

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

    • نام

      رشته

      نام منحصر به فرد این صف. این نام باید منحصر به فرد باشد زیرا برای ثبت رویدادهای همگام سازی و ذخیره درخواست ها در IndexedDB مخصوص این نمونه استفاده می شود. اگر یک نام تکراری شناسایی شود، خطایی ایجاد می شود.

    • گزینه ها

      QueueOptions اختیاری است

    • برمی گرداند
  • نام

    رشته

  • دریافت همه

    خالی

    همه ورودی‌هایی را که منقضی نشده‌اند (به ازای maxRetentionTime ) برمی‌گرداند. هر ورودی منقضی شده از صف حذف می شود.

    تابع getAll به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      Promise<QueueEntry[]>

  • popRequest

    خالی

    آخرین درخواست موجود در صف را حذف می کند و برمی گرداند (همراه با مهر زمانی آن و هر متادیتا). شیء برگشتی به شکل: {request, timestamp, metadata} است.

    تابع popRequest به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      Promise<QueueEntry>

  • pushRequest

    خالی

    درخواست ارسال شده را در IndexedDB (همراه با مهر زمانی و هر ابرداده) در انتهای صف ذخیره می کند.

    تابع pushRequest به نظر می رسد:

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

    • ورود

      QueueEntry

    • برمی گرداند

      قول<باطل>

  • registerSync

    خالی

    یک رویداد همگام سازی را با یک برچسب منحصر به فرد برای این نمونه ثبت می کند.

    تابع registerSync به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      قول<باطل>

  • درخواست های مجدد

    خالی

    از طریق هر درخواست در صف حلقه می زند و سعی می کند دوباره آن را واکشی کند. اگر هر درخواستی دوباره واکشی نشود، در همان موقعیت در صف قرار می‌گیرد (که تلاش مجدد را برای رویداد همگام‌سازی بعدی ثبت می‌کند).

    تابع replayRequests به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      قول<باطل>

  • shiftRequest

    خالی

    اولین درخواست موجود در صف را حذف می کند و برمی گرداند (همراه با مهر زمانی آن و هر متادیتا). شیء برگشتی به شکل: {request, timestamp, metadata} است.

    تابع shiftRequest به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      Promise<QueueEntry>

  • اندازه

    خالی

    تعداد ورودی‌های موجود در صف را برمی‌گرداند. توجه داشته باشید که ورودی های منقضی شده (در هر maxRetentionTime ) نیز در این تعداد گنجانده شده است.

    تابع size به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      قول <تعداد>

  • unshiftRequest

    خالی

    درخواست ارسال شده را در IndexedDB (با مهر زمانی و هر ابرداده ای) در ابتدای صف ذخیره می کند.

    تابع unshiftRequest به نظر می رسد:

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

    • ورود

      QueueEntry

    • برمی گرداند

      قول<باطل>

QueueOptions

خواص

  • forceSyncFallback

    بولی اختیاری

  • maxRetentionTime

    شماره اختیاری

  • onSync

    OnSyncCallback اختیاری است

QueueStore

کلاسی برای مدیریت درخواست‌های ذخیره‌سازی از یک صف در IndexedDB، که برای دسترسی آسان‌تر با نام صف فهرست‌بندی می‌شود.

اکثر توسعه دهندگان نیازی به دسترسی مستقیم به این کلاس ندارند. آن را برای موارد استفاده پیشرفته در معرض.

خواص

  • سازنده

    خالی

    این نمونه را با یک نمونه Queue مرتبط می کند، بنابراین ورودی های اضافه شده را می توان با نام صف آنها شناسایی کرد.

    تابع constructor به نظر می رسد:

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

    • queueName

      رشته

  • حذف ورودی

    خالی

    ورودی شناسه داده شده را حذف می کند.

    اخطار: این روش تضمین نمی کند که ورودی حذف شده متعلق به این صف باشد (یعنی مطابق با queueName باشد). اما این محدودیت قابل قبول است زیرا این کلاس در معرض عموم قرار نمی گیرد. بررسی اضافی این روش را کندتر از آنچه لازم است می کند.

    تابع deleteEntry به شکل زیر است:

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

    • شناسه

      عدد

    • برمی گرداند

      قول<باطل>

  • دریافت همه

    خالی

    همه ورودی‌های فروشگاه مطابق با queueName برمی‌گرداند.

    تابع getAll به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      Promise<QueueStoreEntry[]>

  • popEntry

    خالی

    آخرین ورودی صف مطابق با queueName را حذف می کند و برمی گرداند.

    تابع popEntry به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      Promise<QueueStoreEntry>

  • pushEntry

    خالی

    آخرین ورودی را در صف اضافه کنید.

    تابع pushEntry به نظر می رسد:

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

    • ورود

      UnidentifiedQueueStoreEntry

    • برمی گرداند

      قول<باطل>

  • shiftEntry

    خالی

    اولین ورودی صف مطابق با queueName را حذف می کند و برمی گرداند.

    تابع shiftEntry به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      Promise<QueueStoreEntry>

  • اندازه

    خالی

    تعداد ورودی‌های موجود در فروشگاه را برمی‌گرداند که با queueName مطابقت دارند.

    تابع size به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      قول <تعداد>

  • unshiftEntry

    خالی

    ابتدا یک ورودی را در صف قرار دهید.

    تابع unshiftEntry به نظر می رسد:

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

    • ورود

      UnidentifiedQueueStoreEntry

    • برمی گرداند

      قول<باطل>

StorableRequest

کلاسی برای آسان‌تر کردن سریال‌سازی و سریال‌زدایی درخواست‌ها تا بتوان آنها را در IndexedDB ذخیره کرد.

اکثر توسعه دهندگان نیازی به دسترسی مستقیم به این کلاس ندارند. آن را برای موارد استفاده پیشرفته در معرض.

خواص

  • سازنده

    خالی

    یک شی از داده‌های درخواست را می‌پذیرد که می‌توان از آن برای ساخت یک Request استفاده کرد، اما می‌تواند در IndexedDB نیز ذخیره شود.

    تابع constructor به نظر می رسد:

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

    • درخواست داده

      RequestData

      یک شی از داده‌های درخواست که شامل url به‌علاوه هر ویژگی مرتبط [requestInit] https://fetch.spec.whatwg.org/#requestinit است.

  • شبیه

    خالی

    یک کلون عمیق از نمونه را ایجاد و برمی گرداند.

    تابع clone به نظر می رسد:

    ()=> {...}

  • toObject

    خالی

    یک کلون عمیق از شیء نمونه _requestData را برمی گرداند.

    تابع toObject به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      RequestData

  • به درخواست

    خالی

    این نمونه را به یک درخواست تبدیل می کند.

    تابع toRequest به نظر می رسد:

    ()=> {...}

    • برمی گرداند

      درخواست

  • از درخواست

    خالی

    یک شی Request را به یک شی ساده تبدیل می کند که می تواند ساختاری شبیه سازی شده یا رشته ای JSON داشته باشد.

    تابع fromRequest به نظر می رسد:

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

    • درخواست

      درخواست