国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【譯】客戶端存儲(chǔ)(Client-Side Storage)

dayday_up / 654人閱讀

摘要:本文轉(zhuǎn)載自眾成翻譯譯者文藺鏈接原文介紹本文是關(guān)于客戶端存儲(chǔ)的。因此,瀏覽器對(duì)存儲(chǔ)容量施加了限制。例如,可能會(huì)允許最多存的,的數(shù)據(jù)庫,但因用戶拒絕訪問被禁止使用。語義事件可保持其他標(biāo)簽和窗口同步。

本文轉(zhuǎn)載自:眾成翻譯
譯者:文藺
鏈接:http://www.zcfy.cc/article/660
原文:http://www.html5rocks.com/en/tutorials/offline/storage/

介紹

本文是關(guān)于客戶端存儲(chǔ)(client-side storage)的。這是一個(gè)通用術(shù)語,包含幾個(gè)獨(dú)立但相關(guān)的 API: Web Storage、Web SQL Database、Indexed Database 和 File Access。每種技術(shù)都提供了在用戶硬盤上 —— 而非通常存儲(chǔ)數(shù)據(jù)的服務(wù)器 —— 存儲(chǔ)數(shù)據(jù)的獨(dú)特方式。這么做主要基于以下兩點(diǎn)理由:(a)使 web app 離線可用; (b)改善性能。對(duì)于客戶端存儲(chǔ)使用情況的詳細(xì)闡述,請(qǐng)看 HTML5Rocks 上的文章 《"離線": 這是什么意思?我為何要關(guān)心?》。

這些 API 有著類似的作用范圍和規(guī)則。因此,在去看細(xì)節(jié)之前,我們先了解他們的共同之處吧。

共同特點(diǎn) 基于客戶端的存儲(chǔ)

實(shí)際上,“客戶端時(shí)間存儲(chǔ)”的意思是,數(shù)據(jù)傳給了瀏覽器的存儲(chǔ) API,它將數(shù)據(jù)存在本地設(shè)備中的一塊區(qū)域,該區(qū)域同樣也是它存儲(chǔ)其他用戶特定信息如個(gè)人偏好、緩存的地方。除了存儲(chǔ)數(shù)據(jù),這些 API 可以用來檢索數(shù)據(jù),且在某些情況下還能執(zhí)行搜索和批處理操作。

置于沙盒中的

所有這四個(gè)存儲(chǔ) API 都將數(shù)據(jù)綁到一個(gè)多帶帶的“源”(origin)上。例如,若 http://abc.example.com 保存了一些數(shù)據(jù),那以后瀏覽器就只會(huì)允許 http://abc.example.com 獲取這些數(shù)據(jù)。當(dāng)我們談?wù)摗霸础保╫rigin)的時(shí)候,這意味著域(domain)必須完全相同,所以 http://example.com 和 http://def.example.com 都不行。端口(port)也必須匹配,因此 http://abc.example.com:123 也是不能訪問到 http://abc.example.com (端口默認(rèn)為80)存儲(chǔ)的數(shù)據(jù)。同樣,協(xié)議也必須一樣(像http vs https 等等)。

空間限制(Quotas)

你能想象,如果任何網(wǎng)站都被允許往毫不知情的硬盤里填充以千兆字節(jié)計(jì)的數(shù)據(jù),該有多混亂。因此,瀏覽器對(duì)存儲(chǔ)容量施加了限制。若你的應(yīng)用試圖超出限制,瀏覽器通常會(huì)顯示一個(gè)對(duì)話框,讓用戶確認(rèn)增加。您可能以為瀏覽器對(duì)單個(gè)源(origin)可使用的所有存儲(chǔ)都加以同一多帶帶的限制,但多數(shù)存儲(chǔ)機(jī)制都是多帶帶加以限制的。若 Quota API 被采納,這種情況可能會(huì)改變。但就現(xiàn)在來說,把瀏覽器當(dāng)作一個(gè)二維矩陣,其維度分別是“源”(origin)和“存儲(chǔ)”(storage)。例如, "http://abc.example.com" 可能會(huì)允許最多存 5MB 的 Web Storage, 25MB 的 Web SQL 數(shù)據(jù)庫,但因用戶拒絕訪問被禁止使用 Indexed DataBase。 Quota API 將問題放到一起來看,讓您查詢還有多少可用空間,有多少空間正在使用。

有些情況下,用戶也能先看到有多少存儲(chǔ)將被使用,例如,當(dāng)用戶在 Chrome 應(yīng)用商店中安裝一個(gè)應(yīng)用時(shí),他們將被提示預(yù)先接受其權(quán)限,其中包括存儲(chǔ)限制。(而該應(yīng)用的)manifest 中的可能有個(gè)值是 “unlimited_storage” (無限制存儲(chǔ))。

數(shù)據(jù)庫處理(Transactions)

兩個(gè) “數(shù)據(jù)庫” 的存儲(chǔ)格式支持?jǐn)?shù)據(jù)處理。目的和通常的關(guān)系型數(shù)據(jù)庫使用數(shù)據(jù)處理是一樣的:保證數(shù)據(jù)庫完整。數(shù)據(jù)庫處理(Transactions)防止 “競(jìng)爭(zhēng)條件”(race conditions) —— 這種情況是:當(dāng)兩個(gè)操作序列在同一時(shí)間被應(yīng)用到數(shù)據(jù)庫中, 導(dǎo)致操作結(jié)果都無法被預(yù)測(cè),而數(shù)據(jù)庫也處于可疑的準(zhǔn)確性(dubious accuracy)狀態(tài)。

同步和異步模式(Synchronous and Asynchronous Modes)

多數(shù)存儲(chǔ)格式都支持同步和異步模式。同步模式是阻塞的,意味著下一行 js 代碼執(zhí)行之前,存儲(chǔ)操作會(huì)被完整執(zhí)行。異步模式會(huì)使得后面的 js 代碼在數(shù)據(jù)庫操作完成之前執(zhí)行。存儲(chǔ)操作會(huì)背景環(huán)境中執(zhí)行,當(dāng)操作完成的時(shí)候,應(yīng)用會(huì)以回調(diào)函數(shù)被調(diào)用這種形式接收通知,這個(gè)函數(shù)須在調(diào)用的時(shí)候被指定。

應(yīng)當(dāng)盡量避免使用同步模式,它雖然看起來比較簡(jiǎn)單,但操作完成時(shí)它會(huì)阻塞頁面渲染,在某些情況下甚至?xí)鼋Y(jié)整個(gè)瀏覽器。你可能注意到網(wǎng)站乃至是應(yīng)用出現(xiàn)這種情況,點(diǎn)擊一個(gè)按鈕,結(jié)果所有東西都用不了,當(dāng)你還在想是不是崩潰了?結(jié)果一切又突然恢復(fù)正常了。

某些 API 沒有異步模式,如 “l(fā)ocalStorage”, 使用這些API時(shí),應(yīng)當(dāng)仔細(xì)做好性能監(jiān)測(cè),并隨時(shí)準(zhǔn)備切換到一個(gè)異步API,如果它造成了問題。

API 概述及比較 Web Storage

Web Storage 是一個(gè)叫做 localStorage 的持久對(duì)象。可以使用 localStorage.foo = "bar" 保存值,之后可以使用 localStorage.foo 獲取到 —— 甚至是瀏覽器關(guān)閉之后重新打開。還可以使用一個(gè)叫做 sessionStorage 的對(duì)象,工作方式一樣,只是當(dāng)窗口關(guān)閉之后會(huì)被清除掉。

Web Storage 是 NoSQL 鍵值對(duì)儲(chǔ)存(NoSQL key-value store)的一種.

Web Storage 的優(yōu)點(diǎn)

數(shù)年以來,被所有現(xiàn)代瀏覽器支持, iOS 和 Android 系統(tǒng)下也支持(IE 從 IE8 開始支持 )。

簡(jiǎn)單的API簽名。

同步 API,調(diào)用簡(jiǎn)單。

語義事件可保持其他標(biāo)簽和窗口同步。

Web Storage 的弱點(diǎn)

使用同步 API(這是得到最廣泛支持的模式)存儲(chǔ)大量的或者復(fù)雜的數(shù)據(jù)時(shí)性能差。

缺少索引導(dǎo)致檢索大量的或復(fù)雜的數(shù)據(jù)時(shí)性能差。(搜索操作需要手動(dòng)遍歷所有項(xiàng)。)

存儲(chǔ)或讀取大量的或復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時(shí)性能差,因?yàn)樾枰謩?dòng)序序列化成字符串或?qū)⒆址葱蛄谢V饕臑g覽器實(shí)現(xiàn)只支持字符串(盡管規(guī)范沒這么說的)。

需要保證數(shù)據(jù)的持續(xù)性和完整性,因?yàn)閿?shù)據(jù)是有效非結(jié)構(gòu)化(effectively unstructured)的。

Web SQL Database

Web SQL Database 是一個(gè)結(jié)構(gòu)化的數(shù)據(jù)庫,具備典型 SQL驅(qū)動(dòng)的關(guān)系數(shù)據(jù)庫(SQL-powered relational database)的所有功能和復(fù)雜度。Indexed Database 在兩者之間。Web SQL Database 有自由形式的密鑰值對(duì),有點(diǎn)像 Web Storage,但也有能力從這些值來索引字段,所以搜索速度要快得多。

Web SQL Database 的優(yōu)點(diǎn)

被主要的移動(dòng)瀏覽器(Android Browser, Mobile Safari, Opera Mobile)以及一些 PC 瀏覽器(Chrome, Safari, Opera) 支持。

作為異步 API, 總體而言性能很好。數(shù)據(jù)庫交互不會(huì)鎖定用戶界面。(同步API也可用于 WebWorkers。)

良好的搜索性能,因?yàn)閿?shù)據(jù)可以根據(jù)搜索鍵進(jìn)行索引。

強(qiáng)大,因?yàn)樗С质聞?wù)性數(shù)據(jù)庫模型(transactional database model)。

剛性的數(shù)據(jù)結(jié)構(gòu)更容易保持?jǐn)?shù)據(jù)的完整性。

Web SQL Database 的弱點(diǎn)

過時(shí),不會(huì)被 IE 或 Firefox 支持,在某些階段可能會(huì)被從其他瀏覽器淘汰。

學(xué)習(xí)曲線陡峭,要求掌握關(guān)系數(shù)據(jù)庫和SQL的知識(shí)。

對(duì)象-關(guān)系阻抗失配(object-relational impedance mismatch).

降低敏捷性,因?yàn)閿?shù)據(jù)庫模式必須預(yù)先定義,與表中的所有記錄必須匹配相同的結(jié)構(gòu)。

Indexed Database (IndexedDB)

到目前為止,我們已經(jīng)看到,Web Storage 和 Web SQL Database 都有各種的優(yōu)勢(shì)和弱點(diǎn)。 Indexed Database 產(chǎn)生于這兩個(gè)早期 API 的經(jīng)驗(yàn),可以看作是一種結(jié)合兩者優(yōu)點(diǎn)而不招致其劣勢(shì)得到嘗試。

Indexed Database 是一個(gè) “對(duì)象存儲(chǔ)” (object stores) 的集合,可以直接把對(duì)象放進(jìn)去。這個(gè)存儲(chǔ)有點(diǎn)像 SQL 表,但在這種情況下,對(duì)象的結(jié)構(gòu)沒有約束,所以不需要預(yù)先定義什么。所以這和 Web Storage 有點(diǎn)像,擁有多個(gè)數(shù)據(jù)庫、每個(gè)數(shù)據(jù)庫又有多個(gè)存儲(chǔ)(store)的特點(diǎn)。但不像 Web Storage那樣, 還擁有重要的性能優(yōu)勢(shì): 異步接口,可以在存儲(chǔ)上創(chuàng)建索引,以提高搜索速度。

IndexedDB 的優(yōu)點(diǎn)

作為異步API總體表現(xiàn)良好。數(shù)據(jù)庫交互不會(huì)鎖定用戶界面。(同步 API 也可用于 WebWorkers。)

良好的搜索性能,因?yàn)閿?shù)據(jù)可以根據(jù)搜索鍵進(jìn)行索引。

支持版本控制。

強(qiáng)大,因?yàn)樗С质聞?wù)性數(shù)據(jù)庫模型(transactional database model)。

因?yàn)閿?shù)據(jù)模型簡(jiǎn)單,學(xué)習(xí)曲線也相當(dāng)簡(jiǎn)單。

良好的瀏覽器支持: Chrome, Firefox, mobile FF, IE10.

IndexedDB 的弱點(diǎn)

非常復(fù)雜的API,導(dǎo)致大量的嵌套回調(diào)。

FileSystem

上面的 API 都是適用于文本和結(jié)構(gòu)化數(shù)據(jù),但涉及到大文件和二進(jìn)制內(nèi)容時(shí),我們需要一些其他的東西。幸運(yùn)的是,我們現(xiàn)在有了文件系統(tǒng) API 標(biāo)準(zhǔn)(FileSystem API standard)。它給每個(gè)域一個(gè)完整的層次化的文件系統(tǒng),至少在 Chrome 下面,這些都是用戶的硬盤上的真正的文件。就單個(gè)文件的讀寫而言, API 建立在現(xiàn)有的 File API之上。

FileSystem(文件系統(tǒng)) API 的有點(diǎn)

可以存儲(chǔ)大量的內(nèi)容和二進(jìn)制文件,很適合圖像,音頻,視頻,PDF,等。

作為異步 API, 性能良好。

FileSystem API 的弱點(diǎn)

很早的標(biāo)準(zhǔn),只有 Chrome 和 Opera 支持。

沒有事務(wù)(transaction)支持。

沒有內(nèi)建的搜索/索引支持。

來看代碼

本部分比較不同的 API 如何解決同一個(gè)問題。這個(gè)例子是一個(gè) “地理情緒”(geo-mood) 簽到系統(tǒng),在那里你可以記錄你在時(shí)間和地點(diǎn)的情緒。接口可讓你在數(shù)據(jù)庫類型之間切換。當(dāng)然,在現(xiàn)實(shí)情況中,這可能顯得有點(diǎn)作(contrived),數(shù)據(jù)庫類型肯定比其他的更有意義,文件系統(tǒng) API 根本不適用于這種應(yīng)用!但為了演示的目的,如果我們能看到使用不同方式達(dá)到同樣的結(jié)果,這還是有幫助的。還得注意,為了保值可讀性,一些代碼片段是經(jīng)過重構(gòu)的。

現(xiàn)在可以來試試我們的“地理情緒”(geo-mood)應(yīng)用。

為了讓 Demo 更有意思,我們將數(shù)據(jù)存儲(chǔ)多帶帶拿出來,使用標(biāo)準(zhǔn)的面向?qū)ο蟮脑O(shè)計(jì)技術(shù)(standard object-oriented design techniques)。 UI 邏輯只知道有一個(gè) store;它無需知道 store 是如何實(shí)現(xiàn)的,因?yàn)槊總€(gè) store 的方法是一樣的。因此 UI 層代碼可以稱為 store.setup()store.count() 等等。實(shí)際上,我們的 store 有四種實(shí)現(xiàn),每種對(duì)應(yīng)一種存儲(chǔ)類型。應(yīng)用啟動(dòng)的時(shí)候,檢查 URL 并實(shí)例化對(duì)應(yīng)的 store。

為了保持 API 的一致性,所有的方法都是異步的,即它們將結(jié)果返回給調(diào)用方。Web Storage 的實(shí)現(xiàn)甚至也是這樣的,其底層實(shí)現(xiàn)是本地的。

在下面的演示中,我們將跳過 UI 和定位邏輯,聚焦于存儲(chǔ)技術(shù)。

建立 Store

對(duì) localStorage,我們做個(gè)簡(jiǎn)單的檢驗(yàn)看存儲(chǔ)是否存在。如果不存在,則新建一個(gè)數(shù)組,并將其存儲(chǔ)在 localStorage 的 checkins(簽到) 鍵下面。首先,我們使用 JSON 對(duì)象將結(jié)構(gòu)序列化為字符串,因?yàn)榇蠖鄶?shù)瀏覽器只支持字符串存儲(chǔ)。

if  (!localStorage.checkins) localStorage.checkins = JSON.stringify([]);

對(duì) Web SQL Database,數(shù)據(jù)庫結(jié)構(gòu)如果不存在的話,我們需要先創(chuàng)建。幸運(yùn)的是,如果數(shù)據(jù)庫不存在,openDatabase 方法會(huì)自動(dòng)創(chuàng)建數(shù)據(jù)庫;同樣,使用 SQL 句 “if not exists” 可以確保新的 checkins 表 如果已經(jīng)存在的話不會(huì)被重寫。我們需要預(yù)先定義好數(shù)據(jù)結(jié)構(gòu),也就是, checkins 表每列的名稱和類型。每一行數(shù)據(jù)代表一次簽到。

this.db = openDatabase("geomood", "1.0", "Geo-Mood Checkins", 8192);
this.db.transaction(function(tx) {
    tx.executeSql(
        "create table if not exists "
            + "checkins(id integer primary key asc, time integer, latitude float,"
            + "longitude float, mood string)",
         [], function() {
            console.log("siucc"); 
        }
    );
});

Indexed Database 啟動(dòng)需要一些工作,因?yàn)樗枰獑⒂靡粋€(gè)數(shù)據(jù)庫版本系統(tǒng)。當(dāng)我們連接數(shù)據(jù)庫的時(shí)候要明確我們需要那個(gè)版本,如果當(dāng)前數(shù)據(jù)庫使用的是之前的版本或者還尚未被創(chuàng)建,會(huì)觸發(fā) onupgradeneeded 事件,當(dāng)升級(jí)完成后 onsuccess 事件會(huì)被觸發(fā)。如果無需升級(jí),onsuccess 事件馬上就會(huì)觸發(fā)。

另外一件事就是創(chuàng)建 “mood” 索引,以便之后能很快地查詢到匹配的情緒。

var db;
var version = 1;
window.indexedStore = {};
window.indexedStore.setup = function(handler) { // attempt to open the database
    var request = indexedDB.open("geomood", version);  // upgrade/create the database if needed
    request.onupgradeneeded =  function(event)  {
        var db = request.result;
        if  (event.oldVersion <  1)  { // Version 1 is the first version of the database.
            var checkinsStore = db.createObjectStore("checkins",  { keyPath:  "time"  });
            checkinsStore.createIndex("moodIndex",  "mood",  { unique:  false  });
        }
        if  (event.oldVersion <  2)  {
            // In future versions we"d upgrade our database here. 
            // This will never run here, because we"re version 1.
        }
        db = request.result;
    };
    request.onsuccess =  function(ev)  {  // assign the database for access outside
        db = request.result; handler();
        db.onerror =  function(ev)  {
            console.log("db error", arguments);
        };
    };
};

最后,啟動(dòng) FileSystem。我們會(huì)把每種簽到 JSON 編碼后放在多帶帶的文件中,它們都在 “checkins/” 目錄下面。同樣這并非 FileSystem API 最合適的用途,但對(duì)演示來說還挺好。

啟動(dòng)在整個(gè)文件系統(tǒng)中拿到一個(gè)控制手柄(handle),用來檢查 “checkins/” 目錄。如果目錄不存在,使用 getDirectory 創(chuàng)建。

setup:  function(handler)  {
    requestFileSystem(
        window.PERSISTENT,
        1024*1024,
        function(fs)  {
            fs.root.getDirectory(
                "checkins",
                {},  // no "create" option, so this is a read op
                function(dir)  {
                    checkinsDir = dir;
                    handler();
                }, 
                function()  {
                    fs.root.getDirectory( "checkins",  {create:  true},  function(dir)  { checkinsDir = dir;
                        handler();
                    }, onError );
                }
            );
        },
        function(e)  {
            console.log("error "+e.code+"initialising - see http://goo.gl/YW0TI");
        }  
    );
}
保存一次簽到 (Check-in)

使用 localStorage,我們只需要拿出 check-in 數(shù)組,在尾部添加一個(gè),然后重新保存就行。我們還需要使用 JSON 對(duì)象的方法將其以字符串的方式存起來。

var checkins = JSON.parse(localStorage["checkins"]);
checkins.push(checkin);
localStorage["checkins"] = JSON.stringify(checkins);

使用 Web SQL Database,所有的事情都在 transaction 中進(jìn)行。我們要在 checkins 表 創(chuàng)建新的一行,這是一個(gè)簡(jiǎn)單的 SQL 調(diào)用,我們使用 “?” 語法,而不是把所有的簽到數(shù)據(jù)都放到 “insert” 命令中,這樣更整潔,也更安全。真正的數(shù)據(jù)——我們要保存的四個(gè)值——被放到第二行。“?” 元素會(huì)被這些值(checkin.timecheckin.latitude等等)替換掉。接下來的兩個(gè)參數(shù)是操作完成之后被調(diào)用的函數(shù),分別在成功和失敗后調(diào)用。在這個(gè)應(yīng)用中,我們對(duì)所有操作使用相同的通用錯(cuò)誤處理程序。這樣,成功回調(diào)函數(shù)就是我們傳給搜索函數(shù)的句柄——確保句柄在成功的時(shí)候被調(diào)用,以便操作完成之后 UI 能接到通知(比如,更新目前為止的簽到數(shù)量)。

store.db.transaction(function(tx) {
    tx.executeSql(
        "insert into checkins " + "(time, latitude, longitude, mood) values (?,?,?,?);", 
        [checkin.time, checkin.latitude, checkin.longitude, checkin.mood],
        handler, 
        store.onError
    ); 
});

一旦存儲(chǔ)建立起來,將其存儲(chǔ)到 IndexedDB 中就像 Web Storage 差不多簡(jiǎn)單,還有異步工作的優(yōu)點(diǎn)。

var transaction = db.transaction("checkins",  "readwrite"); 
transaction.objectStore("checkins").put(checkin); 
transaction.oncomplete = handler;

使用 FileSystem API,新建文件并拿到相應(yīng)的句柄,可以用 FileWriter API 進(jìn)行填充。

fs.root.getFile(
    "checkins/" + checkin.time,
    { create: true, exclusive: true }, 
    function(file) {
        file.createWriter(function(writer) {
            writer.onerror = fileStore.onError;
            var bb = new WebKitBlobBuilder;
            bb.append(JSON.stringify(checkin));
            writer.write(bb.getBlob("text/plain"));
            handler(); }, fileStore.onError);
    },
    fileStore.onError
);
搜索匹配項(xiàng)

接下來的函數(shù)找到所有匹配特定情緒的簽到,例如,用戶能看到他們?cè)谧罱螘r(shí)何地過得很開心。使用 localStorage, 我們必須手動(dòng)遍歷每次簽到并將其與搜索的情緒對(duì)比,建立一個(gè)匹配列表。比較好的實(shí)踐是返回存儲(chǔ)數(shù)據(jù)的克隆,而不是實(shí)際的對(duì)象,因?yàn)樗阉鲬?yīng)該是一個(gè)只讀的操作;所以我們將每個(gè)匹配的簽到對(duì)象傳遞給通用的 clone() 方法進(jìn)行操作。

var allCheckins = JSON.parse(localStorage["checkins"]);
var matchingCheckins = [];
allCheckins.forEach(function(checkin) {
    if (checkin.mood == moodQuery) {
        matchingCheckins.push(clone(checkin));
    } 
});
handler(matchingCheckins);

使用 Web SQL Database,我們執(zhí)行一次查詢,只返回我們需要的行。但我們?nèi)孕枰謩?dòng)遍歷來累計(jì)簽到數(shù)據(jù),因?yàn)閿?shù)據(jù)庫 API 返回的是數(shù)據(jù)庫行,而不是一個(gè)數(shù)組。(對(duì)大的結(jié)果集來說這是好事,但就現(xiàn)在而言這增加了我們需要的工作!)

var matchingCheckins = [];
store.db.transaction(function(tx) {
    tx.executeSql(
        "select * from checkins where mood=?",
        [moodQuery],
        function(tx, results) {
            for (var i = 0; i < results.rows.length; i++) {
                matchingCheckins.push(clone(results.rows.item(i)));
            }
            handler(matchingCheckins); 
        },
        store.onError
    );
});

當(dāng)然,在 IndexedDB 解決方案使用索引,我們先前在 “mood” 表中創(chuàng)建的索引,稱為“moodindex”。我們用一個(gè)指針遍歷每次簽到以匹配查詢。注意這個(gè)指針模式也可以用于整個(gè)存儲(chǔ);因此,使用索引就像我們?cè)谏痰昀锏囊粋€(gè)窗口前,只能看到匹配的對(duì)象(類似于在傳統(tǒng)數(shù)據(jù)庫中的“視圖”)。

var store = db.transaction("checkins", "readonly").objectStore("checkins");
var request = moodQuery ? store.index("moodIndex").openCursor(new IDBKeyRange.only(moodQuery)) : store.openCursor();
request.onsuccess = function(ev) {
    var cursor = request.result;
    if (cursor) {
        handler(cursor.value);
        cursor["continue"]();
    } 
};

與許多傳統(tǒng)的文件系統(tǒng)一樣,F(xiàn)ileSystem API 沒有索引,所以搜索算法(如 Unix中的 “grep” 命令)必須遍歷每個(gè)文件。我們從 “checkins/” 目錄中拿到 Reader API ,通過 readentries() 。對(duì)于每個(gè)文件,再使用一個(gè) reader,使用 readastext() 方法檢查其內(nèi)容。這些操作都是異步的,我們需要使用 readnext() 將調(diào)用連在一起。

checkinsDir.createReader().readEntries(function(files) {
    var reader, fileCount = 0,
        checkins = [];
    var readNextFile = function() {
        reader = new FileReader();
        if (fileCount == files.length) return;
        reader.onload = function(e) {
            var checkin = JSON.parse(this.result);
            if (moodQuery == checkin.mood || !moodQuery) handler(checkin);
            readNextFile();
        };

        files[fileCount++].file(function(file) {
            reader.readAsText(file);
        });
    };
    readNextFile();
});
匹配計(jì)數(shù)

最后,我們需要給所有簽到計(jì)數(shù)。

對(duì)localStorage,我們簡(jiǎn)單的反序列化簽到數(shù)組,讀取其長度。

handler(JSON.parse(localStorage["checkins"]).length);

對(duì) Web SQL Database,可以檢索數(shù)據(jù)庫中的每一行(select * from checkins),看結(jié)果集的長度。但如果我們知道我們?cè)?SQL 中,有更容易和更快的方式 —— 我們可以執(zhí)行一個(gè)特殊的 select 語句來檢索計(jì)數(shù)。它將返回一行,其中一列包含計(jì)數(shù)。

store.db.transaction(function(tx) {
    tx.executeSql("select count(*) from checkins;", [], function(tx, results) {
        handler(results.rows.item(0)["count(*)"]);
    }, store.onError);
});

不幸的是, IndexedDB 不提供任何計(jì)算方法,所以我們只能自己遍歷。

var count = 0;
var request = db.transaction(["checkins"], "readonly").objectStore("checkins").openCursor();
request.onsuccess = function(ev) {
    var cursor = request.result;
    cursor ? ++count && cursor["continue"]() : handler(count);
};

對(duì)于文件系統(tǒng), directory reader 的 readentries() 方法提供一個(gè)文件列表,所以我們返回該列表的長度就好。

checkinsDir.createReader().readEntries(function(files)  {
    handler(files.length);
});
總結(jié)

本文從較高層次的角度,講述了現(xiàn)代客戶端存儲(chǔ)技術(shù)。你也可以看看 《離線應(yīng)用概述》(overview on offline apps)這篇文章。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/79781.html

相關(guān)文章

  • []介紹一下漸進(jìn)式 Web App(即時(shí)加載) - Part 2

    摘要:在上一篇,介紹一下漸進(jìn)式離線的文章中,我們討論了典型的應(yīng)該是什么樣子的并且同時(shí)也介紹了。暴露了一個(gè)異步,以避免阻塞的加載。但一些研究表明,在某些情況下,它是阻塞的。打開并且添加如下代碼清除緩存并重新加載。 在上一篇,介紹一下漸進(jìn)式 Web App(離線) - Part 1的文章中,我們討論了典型的pwa應(yīng)該是什么樣子的并且同時(shí)也介紹了 server worker。到目前為止,我們已經(jīng)緩...

    doodlewind 評(píng)論0 收藏0
  • []介紹一下漸進(jìn)式 Web App(即時(shí)加載) - Part 2

    摘要:在上一篇,介紹一下漸進(jìn)式離線的文章中,我們討論了典型的應(yīng)該是什么樣子的并且同時(shí)也介紹了。暴露了一個(gè)異步,以避免阻塞的加載。但一些研究表明,在某些情況下,它是阻塞的。打開并且添加如下代碼清除緩存并重新加載。 在上一篇,介紹一下漸進(jìn)式 Web App(離線) - Part 1的文章中,我們討論了典型的pwa應(yīng)該是什么樣子的并且同時(shí)也介紹了 server worker。到目前為止,我們已經(jīng)緩...

    godlong_X 評(píng)論0 收藏0
  • []介紹一下漸進(jìn)式 Web App(即時(shí)加載) - Part 2

    摘要:在上一篇,介紹一下漸進(jìn)式離線的文章中,我們討論了典型的應(yīng)該是什么樣子的并且同時(shí)也介紹了。暴露了一個(gè)異步,以避免阻塞的加載。但一些研究表明,在某些情況下,它是阻塞的。打開并且添加如下代碼清除緩存并重新加載。 在上一篇,介紹一下漸進(jìn)式 Web App(離線) - Part 1的文章中,我們討論了典型的pwa應(yīng)該是什么樣子的并且同時(shí)也介紹了 server worker。到目前為止,我們已經(jīng)緩...

    YJNldm 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<