2017-02-15 9 views
1

웹에서 많은 기사가 설명하는대로 Service Worker를 사용하여 웹 응용 프로그램에 Push WebAPI를 구현했습니다. 이제 웹 응용 프로그램이 닫히는 동안 (크롬 탭이 닫히고 백그라운드 실행의 서비스 작업자) 닫힌 상태에서 사용할 수 있도록 IndexedDB에 데이터를 저장해야합니다. 특히 (서버에서) 알림 데이터를 검색하는 곳의 간단한 URL을 저장하고 싶습니다. 불행하게도Push WebAPI + IndexedDB + ServiceWorker

self.addEventListener("push", (event) => { 
    console.log("[serviceWorker] Push message received", event); 

    notify({ event: "push" }); // This notifies the push service for handling the notification 

    var open = indexedDB.open("pushServiceWorkerDb", 1); 
    open.onsuccess =() => { 
     var db = open.result; 
     var tx = db.transaction("urls"); 
     var store = tx.objectStore("urls"); 
     var request = store.get("fetchNotificationDataUrl"); 

     request.onsuccess = (ev) => { 
      var fetchNotificationDataUrl = request.result; 
      console.log("[serviceWorker] Fetching notification data from ->", fetchNotificationDataUrl); 

      if (!(!fetchNotificationDataUrl || fetchNotificationDataUrl.length === 0 || !fetchNotificationDataUrl.trim().length === 0)) { 
       event.waitUntil(
        fetch(fetchNotificationDataUrl, { 
         credentials: "include" 
        }).then((response) => { 
         if (response.status !== 200) { 
          console.log("[serviceWorker] Looks like there was a problem. Status Code: " + response.status); 
          throw new Error(); 
         } 

         return response.json().then((data) => { 
          if (!data) { 
           console.error("[serviceWorker] The API returned no data. Showing default notification", data); 
           //throw new Error(); 
           showDefaultNotification({ url: "/" }); 
          } 

          var title = data.Title; 
          var message = data.Message; 
          var icon = data.Icon; 
          var tag = data.Tag; 
          var url = data.Url; 

          return self.registration.showNotification(title, { 
           body: message, 
           icon: icon, 
           tag: tag, 
           data: { 
            url: url 
           }, 
           requireInteraction: true 
          }); 
         }); 
        }).catch((err) => { 
         console.error("[serviceWorker] Unable to retrieve data", err); 

         var title = "An error occurred"; 
         var message = "We were unable to get the information for this push message"; 
         var icon = "/favicon.ico"; 
         var tag = "notification-error"; 
         return self.registration.showNotification(title, { 
          body: message, 
          icon: icon, 
          tag: tag, 
          data: { 
           url: "/" 
          }, 
          requireInteraction: true 
         }); 
        }) 
       ); 
      } else { 
       showDefaultNotification({ url: "/" }); 
      } 
     } 
    }; 
}); 

나는이 예외 보여 작동하지 않는 새로운 푸시 이벤트가 나타납니다 :에 실행하지 못했습니다 'waitUntil'

catch되지 않은 예외 : DOMException을 여기

내 코드입니다 'ExtendableEvent': 이벤트 처리기가 이미 완료되었습니다. IDBRequest.request.onsuccess에서 ( https://192.168.0.102/pushServiceWorker.js:99:23)

어떻게이 문제를 해결할 수 있습니까? 사전

답변

2

event.waitUntil()에 대한 초기 호출이 이벤트 핸들러가 처음 호출 될 때 동 기적으로 수행 될 필요가있는

감사합니다. 그런 다음 promise chain을 event.waitUntil()에 전달하고 약속 체인 내에서 원하는만큼의 비동기 작업을 수행 할 수 있습니다.

event.waitUntil()을 호출하기 전에 현재 코드에서 비동기 IndexedDB 콜백을 호출하므로 해당 오류가 표시됩니다.

약속 체인 내에 IndexedDB 작업을 포함시키는 가장 쉬운 방법은 idb-keyval과 같은 래퍼 라이브러리를 사용하는 것입니다.이 라이브러리는 콜백 기반 IndexedDB API를 사용하여 약속 기반 API로 변환합니다.

귀하의 코드는 다음 볼 수 있었다 같은 것들에 대한

self.addEventListener('push', event => { 
    // Call event.waitUntil() immediately: 
    event.waitUntil(
    // You can chain together promises: 
    idbKeyval.get('fetchNotificationDataUrl') 
     .then(url => fetch(url)) 
     .then(response => response.json()) 
     .then(json => self.registration.showNotification(...) 
); 
}); 
+0

관심이 나는 self.importScripts ('/ libs와/IDB-keyval/DIST/IDB-keyval-min.js')를 사용했습니다; 서비스 작업자로부터 idb-keyval을 사용하는 방법 – Androidian