Travailleurs des services

Dans cet article, je voudrais parler de Service Workers (SW). Les logiciels nous permettent de préparer notre application à fonctionner hors ligne afin qu'elle fonctionne même si nous n'avons pas de connexion Internet. Ils nous permettent également d'utiliser de nombreuses autres fonctionnalités avancées telles que les notifications push ou la synchronisation en arrière-plan. Le logiciel continue de fonctionner même après la fermeture du navigateur, ce qui signifie que les techniciens de service continuent de fonctionner. Il s'agit d'un processus d'arrière-plan. Alors inscrivons notre premier technicien de service.





(Dans cet article, je vais implémenter les fonctionnalités liées à SW en JS simple, puisque le code est écrit en JS brut, nous pouvons l'intégrer dans tous les frameworks JS tels que Angular, React ou Vue)





Dans un premier temps, ajoutez le fichier sw.js à la racine du projet. Dans app.js, nous devons vérifier si SW est disponible dans le navigateur, c'est-à-dire si SW est pris en charge par ce navigateur. Maintenant que nous savons que les logiciels sont disponibles, nous pouvons exécuter la méthode navigator.serviceWorker.register (), en spécifiant le chemin vers le fichier où réside notre logiciel afin de l'enregistrer. Cette méthode renvoie en fait une promesse. Donc, pour obtenir des informations, une fois que c'est fait, nous pouvons le rejoindre.





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» .





Après avoir appuyé sur le bouton "POST DATA", lorsque nous sommes hors ligne, rien ne se passe, mais lorsque la connexion est rétablie, nous constatons que la synchronisation est terminée.









Et afin de confirmer que les données ont bien été envoyées au serveur, nous devons d'abord supprimer notre demande de récupération du cache dynamique et cliquer sur le bouton GET DATA. 









C'est tout pour le moment. À plus tard. Mon code est disponible sur github: https://github.com/Draakan/simplePWA








All Articles