localForage——輕鬆實現 Web 離線儲存

lhb25發表於2014-03-27

  Web 應用程式有離線功能,如儲存大量資料集和二進位制檔案。你甚至可以做快取 MP3 檔案這樣的事情。瀏覽器技術可以儲存離線資料和大量的儲存。但問題是,如何選擇合適技術,如何方便靈活的實現。

  如果你需要開發一個支援離線儲存的 Web 應用程式,不知道從哪裡開始,那麼這篇文章正是你需要的。

  localStorage 能夠讓你實現基本的資料儲存,但它的速度慢,而且不能處理二進位制資料。IndexedDB 和 WebSQL 是非同步的,速度快,支援大資料集,但他們的API 使用起來有點複雜。不僅如此,IndexedDB 和 WebSQL 沒有被所有的主流的瀏覽器廠商支援,這種情況最近也不太可能改變。

  Mozilla 開發了一個叫 localForage 的庫 ,使得離線資料儲存在任何瀏覽器都是一項容易的任務。

  localForage 是一個使用非常簡單的 JavaScript 庫的,提供了 get,set,remove,clear 和 length 等等 API,還具有以下特點:

  • 支援回撥的非同步 API;
  • 支援 IndexedDB,WebSQL 和 localStorage 三種儲存模式(自動為你載入最佳的驅動程式);
  • 支援 BLOB 和任意型別的資料,讓您可以儲存圖片,檔案等等。
  • 支援 ES6 Promises;

  對 IndexedDB 和 WebSQL 的支援使您可以為您的 Web 應用程式儲存更多的資料,要比 localStorage 允許儲存的多很多。其 API 的無阻塞性質使得您的應用程式更快,不會因為 Get/Set 呼叫而掛起主執行緒。

  localStorage

  傳統的  API 在許多方面其實是很不錯的,使用簡單,沒有複雜的資料結構。如果你在你的應用程式有一個配置資訊需要保持,可以這樣寫:

// 需要離線儲存的配置資料
var config = {
    fullName: document.getElementById('name').getAttribute('value'),
    userId: document.getElementById('id').getAttribute('value')
};
 
// 儲存起來,供下次使用
localStorage.setItem('config', JSON.stringify(config));
 
// 從離線儲存中讀取出來
var config = JSON.parse(localStorage.getItem('config'));

  請注意,使用 localStorage 儲存的資料需要儲存為字串,所以我們在儲存和讀取時需要進行 JSON 序列化和反序列化。

  看起來好像使用很簡單,但你很快會發現 localStorage 的幾個問題:

  1. 它是同步的。不管資料多大,我們需要等待資料從磁碟讀取和解析,這會減慢我們的應用程式的響應速度。這在移動裝置上是特別糟糕的,主執行緒被掛起,直到資料被取出,會使你的應用程式看起來慢,甚至沒有反應。

  2. 它僅支援字串。需要使用 JSON.parse 與 JSON.stringify 進行序列號和反序列化。這是因為 localStorage 中僅支援 JavaScript 字串值。不支援數值,布林值,Blob 型別的資料。

  localForage

  localForage 可以解決上面的問題,下面我們對比一下 IndexedDB 和 localForage 儲存相同資料的差異:

  IndexedDB 程式碼:

// IndexedDB.
var db;
var dbName = "dataspace";
var users = [ {id: 1, fullName: 'Matt'}, {id: 2, fullName: 'Bob'} ];
var request = indexedDB.open(dbName, 2);
request.onerror = function(event) {
    // 錯誤處理
};
request.onupgradeneeded = function(event) {
    db = event.target.result;
    var objectStore = db.createObjectStore("users", { keyPath: "id" });
    objectStore.createIndex("fullName", "fullName", { unique: false });
    objectStore.transaction.oncomplete = function(event) {
        var userObjectStore = db.transaction("users", "readwrite").objectStore("users");
    }
};
 
var transaction = db.transaction(["users"], "readwrite");
// 所有資料都新增到資料後呼叫
transaction.oncomplete = function(event) {
    console.log("All done!");
};
transaction.onerror = function(event) {
    // 錯誤處理
};
 
var objectStore = transaction.objectStore("users");
for (var i in users) {
    var request = objectStore.add(users[i]);
    request.onsuccess = function(event) {
        // 裡面包含我們需要的使用者資訊
        console.log(event.target.result);
    };
}

  使用 WebSQL 實現可能不會那麼太冗長,但也是有點複雜。使用 localForage,可以這樣寫:

  localForage 程式碼:

// 儲存使用者資訊
var users = [ {id: 1, fullName: 'Matt'}, {id: 2, fullName: 'Bob'} ];
localForage.setItem('users', users, function(result) {
    console.log(result);
});

  是不是簡單了很多?

  支援不是字串的資料

  比方說,你要下載一個使用者的個人資料圖片,並對其進行快取以供離線使用。使用 localForage 很容易儲存二進位制資料:

// 使用 AJAX 下載圖片
var request = new XMLHttpRequest();
 
// 以獲取第一個使用者的資料圖片為例
request.open('GET', "/users/1/profile_picture.jpg", true);
request.responseType = 'arraybuffer';
 
// 當 AJAX 呼叫完成,把圖片儲存到本地
request.addEventListener('readystatechange', function() {
    if (request.readyState === 4) { // readyState DONE
        // 儲存的是二進位制資料,如果用 localStorage 就無法實現
        localForage.setItem('user_1_photo', request.response, function() {
            // 圖片已儲存,想怎麼用都可以
        });
    }
});
 
request.send()

  下次,只用三行程式碼就可以從快取中把照片讀取出來:

localForage.getItem('user_1_photo', function(photo) {
    // 獲取到圖片資料後,可以通過建立 data URI 或者其它方法來顯示
    console.log(photo);
});

  Callbacks & Promises

  如果你不喜歡在你的程式碼中使用回撥,你可以使用 ES6 Promises,來替換 localForage 的回撥引數。讓我們使用上面的照片例子,看下使用 Promises 的程式碼:

localForage.getItem('user_1_photo').then(function(photo) {
    // 獲取到圖片資料後,可以通過建立 data URI 或者其它方法來顯示
    console.log(photo);
});

  跨瀏覽器支援

  localForage 支援所有現代瀏覽器(包括 IE8 及更高版本)。支援的瀏覽器和平臺如下: 

  • Android Browser 2.1
  • Blackberry 7
  • Chrome 23 (Chrome 4.0 with localStorage)
  • Chrome for Android 32
  • Firefox 10 (Firefox 3.5 with localStorage)
  • Firefox for Android 25
  • Firefox OS 1.0
  • IE 10 (IE 8 with localStorage)
  • IE Mobile 10
  • Opera 15 (Opera 10.5 with localStorage)
  • Opera Mobile 11
  • Phonegap/Apache Cordova 1.2.0
  • Safari 3.1 (includes Mobile Safari)

  GitHub      立即下載

相關文章