前一天,我們再Service Worker
中,導入IndexedDB API
來存取文章,但是我們少改在app.js
中,fetch cache API
資源的部分。
但是,重複在兩個地方寫idb.open
和put
等方法,並不是很理想。
昨天有提到importScript()
可以匯入函式庫,那麼就抽成一個檔案,在透過import
匯入要使用的IndexedDB
功能。
檔名不限定,但在此我就命名為indexedDB.js
var dbPromise = idb.open('articles', 1, function(db){
if(!db.objectStoreNames.contains('article'))
db.createObjectStore('article', {keyPath: 'id'});
});
將Service Worker
中的open
貼到indexedDB.js
。
在Service Worker
,匯入檔案。
importScripts('/src/js/indexedDB.js');
function writeData(table,data){
return dbPromise
.then(function(db){
var transaction = db.transaction(table, 'readwrite');
var article = transaction.objectStore(table);
article.put(data);
return transaction.complete;
});
}
在fetch
事件寫的put
抽成function
fetch(event.request)
.then(function(response){
var copyRes = response.clone();
copyRes.json()
.then(function(data){
for(var key in data){
writeData('article',data[key]);
}
})
})
接著Service Worker
就可以直接丟參數近function
。
原本資源都是放進cache
,Service Worker
對文章的處理已經轉移到IndexedDB
,
所以前面fetch
文章的內容,也要改詢問IndexedDB
有沒有文章。
if ('indexedDB' in window){
readAllData('article')
.then(function(data){
if(!dataFromNetwork){
console.log('IndexedDB Data',data);
updateArticles(data);
}
});
}
readAllData()
是下面在indexedDB.js
寫的一支取article
中,
所有文章內容的功能。
function readAllData(table){
return dbPromise
.then(function(db){
var transaction = db.transaction(table, 'readonly');
var store = transaction.objectStore(table);
return store.getAll();
});
}
這邊因為我只需要讀取Store
中的資料,
在transaction
中,只需要設定readonly
,並回傳getAll()
,取得所有內容。
看到Console
視窗,會看到我們設定的訊息,成功執行Indexed Data
,表示成功囉。
接著,測試離線網頁的反應。
這時候,在IndexedDB
中看到first-post
的image
,是一串firebase
上的url
,
但沒網路情況下,圖片一樣成功載入,為什麼呢?
因為在fetch
時後,資源已經Cache
到dynamic
的紀錄裡面。
到目前為止,從Cache API
轉移到IndexedDB
似乎沒什麼問題呢!