2015-03-23 27 views
8

Nie ma zbyt wielu przykładów wykazujących IndexedDB w ServiceWorker jeszcze, ale te, które widziałam były skonstruowane tak:Dostęp do indexedDB w ServiceWorker. Sytuacja wyścigu

const request = indexedDB.open('myDB', 1); 
var db; 

request.onupgradeneeded = ... 

request.onsuccess = function() { 
    db = this.result; // Average 8ms 
}; 


self.onfetch = function(e) 
{ 
    const requestURL = new URL(e.request.url), 
    path = requestURL.pathname; 

    if(path === '/test') 
    { 
     const response = new Promise(function(resolve) 
     { 
      console.log(performance.now(), typeof db); // Average 15ms 

      db.transaction('cache').objectStore('cache').get('test').onsuccess = function() 
      { 
       resolve(new Response(this.result, { headers: { 'content-type':'text/plain' } })); 
      } 
     }); 

     e.respondWith(response); 
    } 
} 

Czy to może zawieść, gdy ServiceWorker uruchamia się, a jeśli tak to jakie to jest solidny sposób dostępu do indexedDB w ServiceWorker?

Odpowiedz

8

Otwarcie IDB przy każdym uruchomieniu ServiceWorker jest mało prawdopodobne, aby było optymalne, w końcu otworzysz go, nawet jeśli nie jest używany. Zamiast tego otwórz bazę danych, gdy jej potrzebujesz. Singleton jest tutaj bardzo użyteczny (patrz https://github.com/jakearchibald/svgomg/blob/master/src/js/utils/storage.js#L5), więc nie musisz otwierać IDB dwukrotnie, jeśli jest używany dwa razy w ciągu swojego życia.

Zdarzenie "aktywuj" jest świetnym miejscem do otwierania IDB i uruchamiania dowolnych zdarzeń "onupdateneeded", ponieważ stara wersja ServiceWorker nie wchodzi w grę.

4

Nie znam nic specjalnego na temat dostępu do IndexedDB z kontekstu pracownika serwisu poprzez dostęp do IndexedDB za pośrednictwem kontrolowanej strony.

Obietnice w oczywisty sposób ułatwiają życie pracownikowi serwisu, więc znalazłem coś podobnego, np. https://gist.github.com/inexorabletash/c8069c042b734519680c, aby było użyteczne zamiast surowego API IndexedDB. Nie jest to jednak obowiązkowe, o ile tworzysz i zarządzasz własnymi obietnicami odzwierciedlającymi stan asynchronicznych operacji IndexedDB.

Najważniejsze, aby pamiętać przy pisaniu obsługi fetch zdarzeń (i to nie jest specyficzne dla użyciu IndexedDB), jest to, że jeśli zadzwonisz event.respondWith(), trzeba przechodzić zarówno w Response obiektu lub obietnicy to rozwiązanie z obiektem Response. Tak długo, jak to robisz, nie powinno być ważne, czy Twój Response jest zbudowany z wpisów IndexedDB lub API Cache lub gdzie indziej.

Czy napotkasz jakiekolwiek problemy z kodem, który opublikowałeś, czy było to bardziej teoretyczne pytanie?

+0

Teoretyczny. Kod działa poprawnie, ale tylko dlatego, że zdarzenie onsuccess zawsze "wygrywa". Promisingifying indexedDB jest prawdopodobnie właściwym rozwiązaniem. – Adria

+1

Jeśli nie korzystasz z transakcji i po prostu korzystasz z IndexedDB jak localStorage, coś takiego jak ten, z którym się łączyłem, wydaje się działać wystarczająco dobrze. –

+0

To prawda, ale to naprawdę ogranicza zastosowania IndexedDB - tracisz możliwość grupowania operacji w transakcje atomowe i jest naprawdę powolna, gdy wszystko jest w swojej własnej transakcji. – dumbmatter

10

Można owinąć transakcję w obietnicy tak:

var tx = db.transaction(scope, mode); 
var p = new Promise(function(resolve, reject) { 
    tx.onabort = function() { reject(tx.error); }; 
    tx.oncomplete = function() { resolve(); }; 
}); 

Teraz p rozwiąże/odrzucenie po zakończeniu transakcji/przerywa. Więc można zrobić arbitralne logiki w transakcji tx i p.then(...) i/lub przechodzą na utrzymaniu obietnicę w e.respondWith() lub e.waitUntil() itp

Jak zauważył innych komentujących, naprawdę trzeba promisify IndexedDB. Ale skład jego autocommitu po wykonaniu zadania i kolejki mikropasków, które używa Promises, czynią to ... nietrywialnym, aby to zrobić bez całkowitej wymiany API. Ale (jako realizator i jeden z edytorów specyfikacji) aktywnie prototypuję niektóre pomysły.

+0

Warto sprawdzić następujące małe biblioteka, która odzwierciedla indexedDb: https://github.com/jakearchibald/indexeddb-promised – magiccrafter

+0

Witaj z przyszłości! Połączona ("obiecana") biblioteka nie wygląda tak popularnie na NPM i nie widziałem żadnych zmian w specyfikacji. Jako ktoś, kto rozpoczął poważny rozwój JS tuż po ustabilizowaniu się specyfikacji Promise, moją pierwszą myślą o przeczytaniu specyfikacji IDB było "oni * nie mogą * być poważni". Czy była jakaś trakcja na oficjalnej * nowoczesnej wersji tego interfejsu API opartej na oddzwonieniu/opartej na obietnicy, nie obsługującej zdarzeń? – Coderer