عمال الخدمة

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





(في هذه المقالة سأقوم بتنفيذ الوظائف ذات الصلة بالبرنامج في JS العادي ، نظرًا لأن الشفرة مكتوبة بلغة JS العادية ، يمكننا دمجها في أي من أطر عمل JS مثل Angular أو React أو Vue)





كخطوة أولى ، أضف ملف sw.js إلى جذر المشروع. في app.js ، نحتاج إلى التحقق مما إذا كان SW متاحًا في المتصفح ، أي إذا كان SW مدعومًا بواسطة هذا المتصفح. الآن بعد أن علمنا أن SWs متوفرة ، يمكننا تنفيذ طريقة navigator.serviceWorker.register () ، وتحديد المسار إلى الملف حيث يوجد SW الخاص بنا من أجل تسجيله. هذه الطريقة في الواقع ترجع الوعد. لذا ، للحصول على المعلومات ، بمجرد الانتهاء ، يمكننا الانضمام إليه.





if ('serviceWorker' in navigator) {
  navigator.serviceWorker
    .register('/sw.js')
    .then(event => {
      console.log('Service worker registered', event);
    });
}
      
      



SW, . , SW . , . SW, , , self, « SW», addEventListener (). SW , , , , Service Worker’a. , , . , Service Worker .





self.addEventListener('install', event => {
  console.log('Installing [Service Worker]', event);
});
      
      



. Service Worker’a - , , . caches, API , open (), . , . event.waitUntil (). , . . then . cache.addAll () , .





self.addEventListener('install', event => {
  console.log('Installing [Service Worker]', event);

  event.waitUntil(
    caches.open('static')
      .then(cache => {
        console.log('[Service Worker] Precaching App Shell');
        cache.addAll([
          '/',
          '/index.html',
          '/favicon.ico',
          '/src/js/app.js',
          '/src/js/chart.js',
          '/src/js/materialize.js',
          '/src/js/materialize.min.js',
          '/src/css/materialize.css',
          '/src/css/materialize.min.css',
          '/src/css/style.css',
          'https://fonts.googleapis.com/icon?family=Material+Icons',
          'https://code.jquery.com/jquery-2.1.1.min.js',
          'https://cdn.jsdelivr.net/npm/chart.js@2.8.0'
        ]);
      }));
});
      
      



, -.









, . , . , , - . Fetch , - - , css js xhr. , fetch Service Worker’a , . , , .





self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response;
        } else {
          return fetch(event.request);
        }
      })
    );
});
      
      







event.respondWith () , . Service Worker’ , , fetch. , Service Worker, . , , . cashes.match () , . , . , , , , , , . , , , , fetch (event.request). - . 









, - , « » . , , , . , . , . , , , . , .






    Object.keys(pureData).forEach(key => tmp[sorter[key.toLowerCase()]] = { key, value: pureData[key] });

    tmp.forEach(obj => orderedData[obj.key] = obj.value);

    const ctx = document.getElementById('myChart').getContext('2d');

    new Chart(ctx, {
      type: 'line',
      data: {
          labels: Object.entries(orderedData).map(([key, _]) => key),
          datasets: [{
              label: 'Users',
              backgroundColor: '#26a69a',
              borderColor: '#26a69a',
              fill: false,
              data: Object.entries(orderedData).map(([_, value]) => value),
          }]
      }
    });
  });
};
      
      







, , , .





self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response;
        } else {
          return fetch(event.request)
            .then(res => {
              return caches.open('dynamic')
                .then(cache => {
                  cache.put(event.request.url, res.clone());
                  return res;
                })
            });
        }
      })
    );
});
      
      







, , , . , caches, API open (), . cache.put () , . , , - URL- , . - . , , , , . . . . xhr. , css .









. - , . ? SW . , - , , , , indexedDB. , , SW . SW, . , , . , , Service Worker’y . , . - , , API, . Service Worker’y, ready, , . , . , ( ), . , , . , « ». Service Worker’, , , , , .





if ('serviceWorker' in navigator && 'SyncManager' in window) {
      navigator.serviceWorker.ready
        .then(sw => {
          sw.sync.register('sync-request')
        });
    }
      
      







, «POST DATA» , , indexedDB . , indexedDB. , . . - . «sunday», 10 ( :)). writeData utility.js, . - , , - . .





const syncButton = document.getElementById('sync-button');

syncButton.addEventListener('click', _ => {
    if ('serviceWorker' in navigator && 'SyncManager' in window) {
      navigator.serviceWorker.ready
        .then(sw => {
          const data = {
            id: new Date().getTime(),
            sunday: 10
          };

          writeData('sync-requests', data)
            .then(_ => {
              sw.sync.register('sync-request')
            });
        });
    }
});
      
      







, , - . , , .





self.addEventListener('sync', event => {
  console.log('[Service Worker] Syncing');

  if (event.tag === 'sync-request') {
    event.waitUntil(
      readAllData('sync-requests')
        .then(async data => {
          const requests = [];

          for (const d of data) {
            requests.push(fetch('https://simple-pwa-8a005.firebaseio.com/data.json', {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
              },
              body: JSON.stringify({
                sunday: d.sunday
              })
            }));
          }

          const results = await Promise.all(requests);

          results.map((response, index) => {
            if (response.ok) {
              deleteItemFromData('sync-requests', data[index].id);
            }
          })
        })
    );
  }
});
      
      



. event.waitUntil (), , , . , indexedDB ( utility.js), , post , indexedDB, . . . , , «POST DATA» .





بعد الضغط على زر "POST DATA" عندما نكون في وضع عدم الاتصال ، لا يحدث شيء ، ولكن عند استعادة الاتصال ، يمكننا أن نرى أن المزامنة قد اكتملت.









وللتأكد من أن البيانات قد تم إرسالها بالفعل إلى الخادم ، نحتاج أولاً إلى إزالة طلب الجلب من ذاكرة التخزين المؤقت الديناميكية والنقر فوق الزر GET DATA. 









هذا كل شئ حتى الان. أراك لاحقا. الكود الخاص بي متاح على جيثب: https://github.com/Draakan/simplePWA








All Articles