成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

indexedDB事務(wù)功能的Promise化封裝(二)——利用generator完成同步化改造

JackJiang / 2707人閱讀

摘要:在不可以用的前提下,無論是同步化或者鏈?zhǔn)讲僮鞫加貌涣?。于是昨天我自己實現(xiàn)了一個簡單的同步執(zhí)行的,并以此為基礎(chǔ)實現(xiàn)了鏈?zhǔn)讲僮鳌?/p>

前言

本來這個系列應(yīng)該不會這么快更新,然而昨晚寫完前一篇后才發(fā)現(xiàn)我的思路中有一個巨大的漏洞。導(dǎo)致我在前一篇中花費大量時間實現(xiàn)了一個復(fù)雜的Transaction類——其實完全有更簡單的方式來完成這一切。
前篇:http://segmentfault.com/a/1190000003982058
項目地址:https://github.com/woodensail/indexedDB

昨天的疏忽

昨天在設(shè)計封裝庫時,一開始是打算利用《co模塊的前端實現(xiàn)》中實現(xiàn)的async庫來完成數(shù)據(jù)庫訪問的同步化。然而嘗試之后就發(fā)現(xiàn)并不可行,問題在前篇中提到過,出在Promise的機制上。于是得出結(jié)論:indexedDB不可以用原生Promise進行封裝。
在不可以用Promise的前提下,無論是同步化或者鏈?zhǔn)讲僮鞫加貌涣?。于是昨天我自己實現(xiàn)了一個簡單的同步執(zhí)行的Promise,并以此為基礎(chǔ)實現(xiàn)了鏈?zhǔn)讲僮鳌?br>我在昨天的文章寫完之后才突然想到,既然沒有Promise就沒法實現(xiàn)同步化鏈?zhǔn)讲僮?/strong>,那么我自己實現(xiàn)完P(guān)romise后完全可以不用使用鏈?zhǔn)讲僮?,直接一步到位實現(xiàn)同步化。所以這篇文章就是關(guān)于如何完成indexedDB同步化封裝。

使用樣例

這是一段最基礎(chǔ)的用法,依然和昨天一樣實現(xiàn)了get,put,getKV,putKV,四個函數(shù)。
這種寫法下每個操作是多帶帶事務(wù)的,無法保證原子性。

async(function* () {
    var db = yield new DB("test");
    yield db.put("info", {k: "async", v: 1});
    var result1 = yield db.get("info", "async");
    console.log(result1.v);
    
    yield db.putKv("info", "async", "1");
    var result2 = yield db.getKv("info", "async");
    console.log(result2);
}).catch(function (e) {
    console.log(e);
});

首先打開一個事務(wù)然后作為參數(shù)傳遞給數(shù)據(jù)庫訪問函數(shù)即可啟用事務(wù)支持。
下面這兩個操作是在同一個事務(wù)中的。

async(function* () {
    var db = yield new DB("test");
    var tx = db.transaction("info", "readwrite");
    yield db.put("info", {k: "async", v: 1}, tx);
    var result1 = yield db.get("info", "async", tx);
    console.log(result1.v);
}).catch(function (e) {
    console.log(e);
});

在開啟事務(wù)時,第三個參數(shù)填true,可以將當(dāng)前事務(wù)作為默認(rèn)事務(wù)。后面的操作將自動使用該事務(wù)。需要在使用完畢后調(diào)用transactionEnd手動清除默認(rèn)事務(wù)。

async(function* () {
    var db = yield new DB("test");
    db.transaction("info", "readwrite", true);
    yield db.put("info", {k: "async", v: 1});
    var result1 = yield db.get("info", "async");
    console.log(result1.v);
    db.transactionEnd();
}).catch(function (e) {
    console.log(e);
});
實現(xiàn)Promise

這是一個不完全版的Promise實現(xiàn),只提供了最基本的then和catch以及他們的鏈?zhǔn)秸{(diào)用。反正也夠async用了。
暫時沒有提供對Promise.all的支持,我估計要支持得修改async庫才行,所以就以后再說吧。

var DbPromise = function (fun) {
    this.state = "pending";
    this.resolveList = [];
    this.rejectList = [];
    var _this = this;
    fun(function () {
        _this.resolve.apply(_this, arguments)
    }, function () {
        _this.reject.apply(_this, arguments)
    });
};
DbPromise.prototype = {};
DbPromise.prototype.resolve = function (data) {
    this.state = "resolved";
    this.data = data;
    var _this = this;
    this.resolveList.forEach(function (fun) {
        _this.data = fun(_this.data)
    });
};
DbPromise.prototype.reject = function (data) {
    this.state = "rejected";
    this.error = data;
    this.rejectList.forEach(function (fun) {
        fun(data);
    });
};
DbPromise.prototype.then = function (fun) {
    if (this.state === "pending") {
        this.resolveList.push(fun);
    } else {
        this.data = fun(this.data);
    }
    return this;
};
DbPromise.prototype.catch = function (fun) {
    if (this.state === "pending") {
        this.rejectList.push(fun);
    } else {
        fun(this.error);
    }
    return this;
};
實現(xiàn)數(shù)據(jù)庫封裝類

定義class DB,打開數(shù)據(jù)庫的操作定義在_open中,會在后面介紹

var DB = function (name, upgrade, version) {
    var _this = this;
    // 可以在其他js文件中通過向DB.dbMap添加成員的方式來預(yù)定義數(shù)據(jù)庫
    // 如果是已經(jīng)預(yù)定義過的數(shù)據(jù)庫就可以調(diào)用new DB(name)來打開
    // 否則需要調(diào)用new DB(name, upgrade, version),填寫upgrade響應(yīng)函數(shù)和版本號
    if (DB.dbMap[name]) {
        var map = DB.dbMap[name];
        return _open(name, map.upgrade, map.version).then(function (db) {
            _this.db = db;
            return _this;
        }).then(map.nextStep);
    } else {
        return _open(name, upgrade, version).then(function (db) {
            _this.db = db;
            return _this;
        });
    }
};
DB.prototype = {};

打開事務(wù)和取消關(guān)閉事務(wù)的方法。

DB.prototype.transaction = function (table, type, asDefault) {
    // 根據(jù)給定的目標(biāo)和類型打開當(dāng)前數(shù)據(jù)庫的事務(wù)
    var tx = _transaction(this.db, table, type);
    // 如果asDefault為真,則緩存該事務(wù)將其作為默認(rèn)事務(wù)。
    // 注意目前同時設(shè)置多個默認(rèn)事務(wù)是會沖突的,
    // 這種情況理論上有極小的可能性在異步操作中出現(xiàn),我會在接下來的版本中改正這一點。
    if (asDefault) {
        this.tx = tx;
    }
    return tx;
};
//取消默認(rèn)事務(wù)
DB.prototype.transactionEnd = function () {
    this.tx = void 0;
};
function _transaction(db, table, type) {
    return db.transaction(table, type);
}

具體的數(shù)據(jù)庫操作函數(shù)。其實是對_put等函數(shù)的封裝。

// tx || this.tx 指的是優(yōu)先使用參數(shù)指定的事務(wù),其次使用默認(rèn)事務(wù)
DB.prototype.put = function (table, data, tx) {
    return _put(this.db, table, data, tx || this.tx);
};
DB.prototype.get = function (table, name, tx) {
    return _get(this.db, table, name, tx || this.tx);
};
DB.prototype.clear = function (table, tx) {
    return _clear(this.db, table, tx || this.tx);
};

//這兩個是對get和put的特殊封裝,多了參數(shù)和結(jié)果的預(yù)處理,簡化了參數(shù)和返回值的格式
DB.prototype.getKv = function (table, k, tx) {
    return _get(this.db, table, k, tx).then(o=>(o || {}).v);
};
DB.prototype.putKv = function (table, k, v, tx) {
    return _put(this.db, table, {k, v}, tx);
};

_open,_put,_get,_clear的實現(xiàn)由于后三者類似,所以只貼了_put。需要后兩點代碼請查看github。

function _open(name, upgrade, version) {
    // 返回自定義Promise供async庫調(diào)用
    return new DbPromise(function (resolve, reject) {
        // 打開指定數(shù)據(jù)庫的指定版本
        var request = indexedDB.open(name, version);
        // 設(shè)置升級操作
        request.onupgradeneeded = upgrade;
        // 綁定success和error,其中成功后會返回打開的數(shù)據(jù)庫對象
        request.onsuccess = function (e) {
            resolve(request.result);
        };
        request.onerror = reject;
    });
}
function _put(db, table, data, tx) {
    // 返回自定義Promise供async庫調(diào)用
    return new DbPromise(function (resolve, reject) {
        // 如果沒有提供事務(wù)則創(chuàng)建新事務(wù)
        tx = tx || db.transaction(table, "readwrite");
        // 打開store并進行操作
        var store = tx.objectStore(table);
        var request = store.put(data);
        // 設(shè)置回調(diào)
        request.onsuccess = function () {
            resolve(request.result);
        };
        request.onerror = reject;

    });
}
總結(jié)

基本上,在實現(xiàn)了DbPromise之后其他部分的實現(xiàn)方式就是按老一套來就行了,非常的簡單。我昨天只是光棍節(jié)腦袋抽筋沒反應(yīng)過來而已。
現(xiàn)在的庫已經(jīng)可以當(dāng)做基本的Key-Value數(shù)據(jù)庫來用了,以后我會進一步添加更多的方法。各位親們,推薦或者收藏一下唄。

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86179.html

相關(guān)文章

  • indexedDB事務(wù)功能Promise封裝

    摘要:綜上,對進行一定的封裝,來簡化編碼操作。化的嘗試對于這種帶大量回調(diào)的,使用進行異步化封裝是個好主意。因此包括在內(nèi)的所有異步方法都會強制中止當(dāng)前事務(wù)。這就決定了一個事務(wù)內(nèi)部的所有操作必須是同步完成的。目前只實現(xiàn)了和,其他的有待下一步工作。 前言 本文是介紹我在編寫indexedDB封裝庫中誕生的一個副產(chǎn)品——如何讓indexedDB在支持鏈?zhǔn)秸{(diào)用的同時,保持對事務(wù)的支持。項目地址:htt...

    zombieda 評論0 收藏0
  • 基于promise對象兩種類庫q庫和bluebird基礎(chǔ)調(diào)用和原理

    摘要:上一節(jié)講述了的原理及實現(xiàn),這一節(jié)為大家?guī)韮蓚€基于封裝的庫,方便我們在項目實戰(zhàn)中能夠方便采用處理異步。的方法,也是生成一個成功的對象,但是確是將的參數(shù)傳入對象成功回調(diào)中作為成功回調(diào)參數(shù)。對象和的處理方式和調(diào)用方式相同。 上一節(jié)講述了promise的原理及實現(xiàn),這一節(jié)為大家?guī)韮蓚€基于promise封裝的庫,方便我們在項目實戰(zhàn)中能夠方便采用promise處理異步。 一、q庫 www.n...

    Travis 評論0 收藏0
  • 深入探析koa之異步回調(diào)處理篇

    摘要:而之后,我們得到的是一個是一個對象,我們可以使用語句定義回調(diào)函數(shù),函數(shù)的內(nèi)容呢,則是將讀取到的返回給并繼續(xù)讓從斷點處執(zhí)行。 在上一篇中我們梳理了koa當(dāng)中中間件的洋蔥模型執(zhí)行原理,并實現(xiàn)了一個可以讓洋蔥模型自動跑起來的流程管理函數(shù)。這一篇,我們再來研究一下koa當(dāng)中異步回調(diào)同步化寫法的原理,同樣的,我們也會實現(xiàn)一個管理函數(shù),是的我們能夠通過同步化的寫法來寫異步回調(diào)函數(shù)。 1. 回調(diào)金字...

    Drinkey 評論0 收藏0
  • IndexedDB 打造靠譜 Web 離線數(shù)據(jù)庫

    摘要:設(shè)置為參數(shù)設(shè)置指定索引,并確保唯一性上面主要做了件事打開數(shù)據(jù)庫表新建,并設(shè)置設(shè)置打開數(shù)據(jù)庫表主要就是版本號和名字,沒有太多講的,我們直接從創(chuàng)建開始吧。打開注意事項檢查是否支持版本更新在生成一個實例時,需要手動指定一個版本號。 在知乎和我在平常工作中,常常會看到一個問題: 前端現(xiàn)在還火嗎? 這個我只想說: 隔岸觀火的人永遠(yuǎn)無法明白起火的原因,只有置身風(fēng)暴,才能找到風(fēng)眼之所在 ——『秦時明...

    孫吉亮 評論0 收藏0
  • Understanding PWA

    摘要:安裝事件綁定在文件中,當(dāng)安裝成功后,事件就會被觸發(fā)。激活當(dāng)安裝完成后并進入激活狀態(tài),會觸發(fā)事件。這會導(dǎo)致更新得不到響應(yīng)。由兩個構(gòu)成用來顯示系統(tǒng)的通知用來處理下發(fā)的消息這兩個都是建立在在基礎(chǔ)上的,在后臺響應(yīng)推送消息時間,并把他們傳遞給應(yīng)用。 showImg(https://segmentfault.com/img/bVbhbQf?w=1182&h=656); 原文地址: https://...

    EsgynChina 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<