автономный ответ рабочего окна от IDB вместо кеша

Я создаю приложение vueJs с сервис-воркером. Я решил использовать Workbox с методом InjestManifest, чтобы иметь свои собственные маршруты.

при загрузке, когда онлайн: 1- ответ по сети 2- отправка тела в IDB (через localforage) 3- отправка ответа

здесь все работает отлично, sw перехватывает выборку и возвращается с соответствующим ответом, IDB содержит все подробности. ответ, отправленный обратно в fecth при подключении к Интернету: Response {type: "cors", url: "http://localhost:3005/api/events ", перенаправлено: false, status: 200, ok: true,…}

проблема в том, когда я перехожу в офлайн. мой идентификатор намерения подключиться к Locaforage и получить контент и создать ответ. Проблема в том, что этот ответ не считается подходящим для Fetch, который затем отклоняет его. Console.log подтверждает, что .catch в sw работает, но похоже, что отправленный ответ отклонен. вот console.log ответа, который я отправляю обратно, чтобы получить его в автономном режиме; Ответ {type: "default", url: "", redirected: false, status: 200, ok: true,…}

Я не знаю, не устраивает ли выборка, потому что URL-адрес ответа не такой, как в запросе, но рабочее поле должно позволять отвечать другими ответами, кроме тех, которые поступают из кеша или выборки.

вот код

importScripts('localforage.min.js')

localforage.config({
  name: 'Asso-corse'
})
workbox.skipWaiting()
workbox.clientsClaim()

workbox.routing.registerRoute(
  new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
  workbox.strategies.cacheFirst({
    cacheName: 'googleapis',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 30
      })
    ]
  })
)
workbox.routing.registerRoute( new RegExp('http://localhost:3005/api/'), function (event) {
  fetch(event.url)
    .then((response) => {
      var cloneRes = response.clone()
      console.log(cloneRes)
      cloneRes.json()
      .then((body) => {
        localforage.setItem(event.url.pathname, body)
      })
      return response
    })
    .catch(function (error) {
      console.warn(`Constructing a fallback response, due to an error while fetching the real response:, ${error}`)
        localforage.getItem(event.url.pathname)
        .then((res) => {
         let payload = new Response(JSON.stringify(res), { "status" : 200 , 
    "statusText" : "MyCustomResponse!" })
         console.log(payload)
        return payload
        })
  })
    })
workbox.precaching.precacheAndRoute(self.__precacheManifest || [])

Я действительно застрял там, поскольку вся документация по рабочему ящику связана с использованием кеша. Я использую localforage, поскольку он поддерживает обещания, которые необходимы для работы автономной работы.

Спасибо


person Gerald M    schedule 06.06.2018    source источник
comment
Я использую localforage, поскольку он поддерживает обещания, которые необходимы для работы автономной работы. Не могли бы вы объяснить, что вы имеете в виду? Cache Storage API также использует обещания и работает асинхронно, и он определенно предназначен для обработки этого варианта использования.   -  person Jeff Posnick    schedule 06.06.2018
comment
Я имел в виду это, чтобы объяснить, почему я использую Localforage вместо IDB. но я хочу использовать такое хранилище, потому что оно также является частью стандартных рекомендаций (developers.google.com/web/ilt/pwa/): общие рекомендации по хранению данных заключаются в том, что ресурсы с URL-адресами должны храниться с интерфейсом Cache, а другие данные должны храниться с IndexedDB. Например, файлы HTML, CSS и JS должны храниться в кеше, а данные JSON должны храниться в IndexedDB. Я понимаю, что с кеш-хранилищем мне было бы проще.   -  person Gerald M    schedule 06.06.2018
comment
Ресурсы с URL-адресом должны храниться с интерфейсом Cache ... ваши данные JSON происходят из HTTP API и имеют соответствующий URL-адрес (начинающийся с пути /api/ в вашем примере), поэтому он доступен для URL-адреса. Я бы рекомендовал придерживаться API хранилища кэша для этого варианта использования.   -  person Jeff Posnick    schedule 06.06.2018
comment
Спасибо, Джефф, это, конечно, то, что я сделаю, но я удивлен, увидев, что интеграция с IDB нигде не рассматривается, поскольку это часть стандартных рецептов для поддержки локальной базы данных. API - это бэкэнд, который я создаю, и когда мне нужно будет опубликовать данные. Мой план также заключался в том, чтобы использовать сервис-воркера для синхронизации данных. Имеет смысл поддерживать чистое хранилище IDB.   -  person Gerald M    schedule 06.06.2018
comment
@GeraldM: У меня такая же настройка, как и у вас, в одном из моих локальных проектов (который находится в angular 6), например, чтение с использованием localforage в качестве резервного ответа в автономном режиме. Единственное, что у меня registerroute на firebase API. Обработчик catch вызывается, но мой собственный ответ не работает. Я тоже возвращаю ответ. Но все равно не работает. Любая идея ? Я пробую это на локальном хосте, а не в живой среде.   -  person Amit    schedule 11.09.2018


Ответы (1)


Ваш catch() обработчик должен вернуть либо объект Response, либо обещание для объекта Response.

Немного изменив форматирование вашего примера кода, вы сейчас делаете:

.catch(function (error) {
  console.warn(`Constructing a fallback response, due to an error while fetching the real response:, ${error}`)
  localforage.getItem(event.url.pathname).then((res) => {
    let payload = new Response(JSON.stringify(res), { "status" : 200 , "statusText" : "MyCustomResponse!" })
    console.log(payload)
    return payload
  })
})

Основываясь на этом форматировании, я думаю, становится яснее, что вы не возвращаете ни Response, ни обещание для Response из вашего catch() обработчика - вы вообще ничего не возвращаете.

Добавление return перед оператором localforage.getItem(...) должно позаботиться об этом:

.catch(function (error) {
  console.warn(`Constructing a fallback response, due to an error while fetching the real response:, ${error}`)
  return localforage.getItem(event.url.pathname).then((res) => {
    let payload = new Response(JSON.stringify(res), { "status" : 200 , "statusText" : "MyCustomResponse!" })
    console.log(payload)
    return payload
  })
})

Но, как упоминалось в комментариях к вашему исходному вопросу, я не думаю, что использование IndexedDB для хранения этого типа данных с URL-адресацией необходимо. Вы можете просто положиться на API Cache Storage, который Workbox с радостью будет использовать по умолчанию при хранении и извлечении данных JSON, полученных из HTTP API.

person Jeff Posnick    schedule 06.06.2018
comment
это сработало, большое спасибо. Я обязательно создам еще одну версию, использующую Cache Storage API, и посмотрю, охватывает ли она все варианты использования, которые приложение должно будет покрыть. - person Gerald M; 06.06.2018
comment
Привет, Джефф, я должен признать, что API хранилища кэша отлично справляется. одна строка кода, и все готово. Я многому научился на этом опыте, и важно поэкспериментировать, чтобы узнать, какие варианты являются наиболее ценными. Пока что Workbox работает очень хорошо. - person Gerald M; 07.06.2018
comment
Рад это слышать! - person Jeff Posnick; 07.06.2018
comment
Привет, @JeffPosnick. Мы пытаемся сделать приложение офлайн. Но мы используем API-интерфейсы SOAP, и конечная точка URL всегда будет одинаковой по отношению к любой веб-службе, запускаемой нашим приложением. В этом случае, как мы должны обрабатывать ответ API, когда пользователь находится в автономном режиме. Поскольку Cache API основан на URL-адресах, есть ли способ справиться с этим сценарием с помощью API кеша? - person Amit; 10.09.2018