Сервисный работник обнаружил, что кэш завершен - PullRequest
0 голосов
/ 24 февраля 2019

У моего PWA большая загрузка данных.Я хочу отобразить страницу загрузки «Пожалуйста, подождите ...» и дождаться завершения кэширования, прежде чем запускать полное приложение.Поэтому мне нужно определить, когда все кэширование завершено.Фрагмент моего работника сервиса:

let appCaches = [{
    name: 'pageload-core-2018-02-14.002',
    urls: [
      './',
      './index.html',
      './manifest.json',
      './sw.js',
      './sw-register.js'
    ]
  },
  {
    name: 'pageload-icon-2018-02-14.002',
    urls: [
      './icon-32.png',
      './icon-192.png',
      './icon-512.png'
    ]
  },
  {
    name: 'pageload-data-2019-02-14.002',
    urls: [
      './kjv.js'
    ]
  }
];

let cacheNames = appCaches.map((cache) => cache.name);

self.addEventListener('install', function (event) {
  console.log('install');
  event.waitUntil(caches.keys().then(function (keys) {
    return Promise.all(appCaches.map(function (appCache) {
      if (keys.indexOf(appCache.name) === -1) {
        caches.open(appCache.name).then(function (cache) {
          return cache.addAll(appCache.urls).then(function () {
            console.log(`Cached: ${appCache.name} @ ${Math.floor(Date.now() / 1000)}`);
          });
        });
      } else {
        console.log(`Found: ${appCache.name}`);
        return Promise.resolve(true);
      }
    })).then(function () {
      // Happens first; expected last.
      console.log(`Cache Complete @ ${Math.floor(Date.now() / 1000)}`);
    });
  }));
  self.skipWaiting();
});

Когда я тестирую это с симулированной сетью 3G, трассировка:

enter image description here

Я не понимаю, почему сообщение «Cache Complete» регистрируется перед тем, как регистрируется какое-либо отдельное сообщение «Cache»;Я ожидаю, что это будет последним.Есть ли что-то другое в поведении Promise.all по сравнению с другими обещаниями?

1 Ответ

0 голосов
/ 24 февраля 2019

Ой!Какой глупый недосмотр.После разбиения цепочки обещаний на отдельные обещания и пошагового выполнения кода проблема стала очевидной.

self.addEventListener('install', function (event) {
  console.log('install');
  event.waitUntil(caches.keys().then(function (keys) {
    return Promise.all(appCaches.map(function (appCache) {
      if (keys.indexOf(appCache.name) === -1) {
        // Never returned the promise chain to map!!!
        return caches.open(appCache.name).then(function (cache) {
          return cache.addAll(appCache.urls).then(function () {
            console.log(`Cached: ${appCache.name} @ ${Math.floor(Date.now() / 1000)}`);
          });
        });
      } else {
        console.log(`Found: ${appCache.name}`);
        return Promise.resolve(true);
      }
    })).then(function () {
      console.log(`Cache Complete @ ${Math.floor(Date.now() / 1000)}`);
    });
  }));
  self.skipWaiting();
});

Я никогда не возвращал цепочку обещаний в функцию map (без явного return всегда возвращает undefined).Таким образом, массив, переданный в Promise.all, содержит только undefined значений.Поэтому он немедленно разрешил и, следовательно, записал свое сообщение перед другими.

enter image description here

Живи и учись ...

...