在瀏覽器中使用SQLite(官方sqlite3.wasm)

有人可能會問:既然瀏覽器里又內置得IndexedDB,而且在IndexedDB里存數據,關了瀏覽器數據也不會丟,為什么還要在瀏覽器里用SQLite?

實際上,當 IndexedDB 內的數據量增多,數據和數據之間的關系變得復雜,IndexedDB 的劣勢就凸顯出來了。我們在這方面踩過很多坑,這里就不細說了。

好了,言歸正傳:

我建議你不要使用這個工具:https://github.com/sqlite/sqlite-wasm,用起來麻煩的很,而且類型定義還有問題(看看 issue 就知道了)。

還是自己使用原始的、官方提供的 js 文件比較好。

首先到? SQLite Download Page?下載?WebAssembly & JavaScript 版本的SQLite。

下載解壓后你將得到:

我們需要的文件都在 jswasm 目錄中。

把 jswasm 目錄中的如下文件拷貝到你的根目錄下,(可以通過 https://domain.com/sqlite3.js 訪問)

接著,在你的頁面引入?sqlite3-worker1-promiser.js 腳本文件

<script src="sqlite3-worker1-promiser.js"></script>

現在我們封裝一個 TypeScript 類

class Db {dbId: string;dbFunc: (cmd: string, param: object) => Promise<{ dbId: string; messageId: string; type: string; result: any }>;constructor() {}exec(sql: string): Promise<any[]> {return new Promise((resolve, reject) => {let rows = [];this.dbFunc("exec", {dbId: this.dbId,sql,callback: (result: { columnNames: string[]; row: any[]; rowNumber: number; type: string }) => {if (result.row) {let obj = {};for (let i = 0; i < result.columnNames.length; i++) {obj[result.columnNames[i]] = result.row[i];}rows.push(obj);} else {resolve(rows);}},});});}async open() {const dbFactory = globalThis.sqlite3Worker1Promiser.v2;delete globalThis.sqlite3Worker1Promiser;const config = {debug: (...args) => console.debug("db worker debug", ...args),onunhandled: (ev) => console.error("Unhandled db worker message:", ev.data),onerror: (ev) => console.error("db worker error:", ev),};this.dbFunc = await dbFactory(config);let { dbId } = await this.dbFunc("open", {filename: "file:db.sqlite3?vfs=opfs",simulateError: 0,});this.dbId = dbId;let rows = await this.exec(`SELECT name FROM sqlite_master WHERE type='table' AND name='Job';`);if (rows.length <= 0) {await this.exec(`CREATE TABLE Job(Id VARCHAR2(36) NOT NULL PRIMARY KEY, JobInfo TEXT, RepeatType INT, StartTime BIGINT, EndTime BIGINT, ColorIndex INT);
CREATE INDEX JobInfo_Index ON Job(JobInfo);
CREATE TABLE Setting(ViewDefault INT DEFAULT 0, ViewVal INT, LangDefault INT DEFAULT 0, SkinDefault INT DEFAULT 0, AlertBefore INT);
INSERT INTO Setting (ViewDefault, ViewVal, LangDefault, SkinDefault, AlertBefore) VALUES (0, 0, 0, 0, 5);`);}let data = await this.exec(`select * from Setting;`);console.log(data);}async delDb() {const opfsRoot = await navigator.storage.getDirectory();await opfsRoot.removeEntry("db.sqlite3");}
}
export let db = new Db();

先來看打開數據庫方法:?open 。

我們使用 SQLite3 的 V2 版本的方法,其他老方法一股腦刪掉。

const dbFactory = globalThis.sqlite3Worker1Promiser.v2;
delete globalThis.sqlite3Worker1Promiser;

接著創建一個數據庫訪問方法:dbFunc,然后使用這個方法創建數據庫:db.sqlite3

this.dbFunc = await dbFactory(config);
let { dbId } = await this.dbFunc("open", {filename: "file:db.sqlite3?vfs=opfs",simulateError: 0,
});

注意,filename的路徑和參數,我們讓數據庫保存在瀏覽器的OPFS文件系統中。

OPFS 是瀏覽器提供的一種私有文件系統,屬于 File System Access API 的一部分。它的特點包括:

私有性:每個網站擁有獨立的文件系統,其他網站無法訪問。

高性能:支持原地讀寫和同步訪問,適合數據庫等對性能要求高的場景。

持久化:數據不會因刷新或關閉瀏覽器而丟失。

?數據文件創建成功后,將得到數據庫id:dbId,這是個字符串。

接下來,我們檢查數據庫中是否存在指定的表,沒有的話,就給數據庫建表。

此時就用到了SQL指令執行方法:exec

執行 SQL 指令,也是用 dbFunc 方法完成的。

如果執行的 SQL 語句本身不返回數據(例如 INSERT, UPDATE, DELETE, 或查詢結果為空的 SELECT),回調方法 callback 只會被執行一次。callback 的傳入參數 result 沒有 row 屬性。

如果執行的 SQL 語句本身返回多行數據,那么 callback 方法會被執行多次,每次都可能返回多行查詢結果,查詢結果被存儲在 result 的 row 屬性里,最后一次 callback 方法被執行時, result 沒有 row 屬性,表示查詢結束。

下面這段代碼用來根據列名構造數據對象:

if (result.row) {let obj = {};for (let i = 0; i < result.columnNames.length; i++) {obj[result.columnNames[i]] = result.row[i];}rows.push(obj);
} else {resolve(rows);
}

如果你想刪除數據庫,可以使用 delDb 方法

const opfsRoot = await navigator.storage.getDirectory() 用于獲取 OPFS 文件系統的根目錄實例

opfsRoot.removeEntry(name) 會從當前目錄中刪除名為 "db.sqlite3" 的文件或子目錄。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/89878.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/89878.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/89878.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構(Java)--位運算

前言 本文為本小白學習數據結構的筆記&#xff0c;將以算法題為導向&#xff0c;向大家更清晰的介紹數據結構相關知識&#xff08;算法題都出自B站馬士兵教育——左老師的課程&#xff0c;講的很好&#xff0c;對于想入門刷題的人很有幫助&#xff09; 為什么要使用為位運算 位…

秋招Day14 - Redis - 應用

Redis如何實現異步消息隊列&#xff1f; List配合LPUSH和RPOP。 另外就是用 Redis 的 Pub/Sub 來實現簡單的消息廣播和訂閱。 但是這兩種方式都是不可靠的&#xff0c;因為沒有 ACK 機制所以不能保證訂閱者一定能收到消息&#xff0c;也不支持消息持久化。 Redis如何實現延時…

因果語言模型、自回歸語言模型、僅解碼器語言模型都是同一類模型

因果語言模型、自回歸語言模型、僅解碼器語言模型都是同一類模型 flyfish 因果語言模型&#xff08;causal Language Models&#xff09; 自回歸語言模型&#xff08;autoregressive language models&#xff09; 僅解碼器語言模型&#xff08;decoder-only language models&am…

jvm架構原理剖析篇

簡單題&#xff08;5道&#xff09; 考查內容&#xff1a;JVM運行時數據區域 題干&#xff1a;Java虛擬機棧的主要作用是&#xff1f; A. 存儲對象實例 B. 存儲方法調用和局部變量 C. 存儲靜態字段 D. 存儲字節碼指令 正確答案&#xff1a;B 解析&#xff1a;虛擬機棧用于存儲方…

智鏈萬物:人工智能驅動的產業智能化革命

當生成式AI在藝術與創意領域掀起風暴&#xff0c;大型語言模型重塑信息交互方式時&#xff0c;一場更為基礎、影響更為深遠的變革&#xff0c;正在全球實體經濟的根基處悄然發生并加速推進——這就是產業智能化。它并非簡單的“機器換人”&#xff0c;而是人工智能&#xff08;…

python中上下文管理器 與 try finally有什么區別

目錄 主要區別代碼對比何時使用哪種方式 主要區別 語法簡潔性 上下文管理器使用 with 語句&#xff0c;語法更簡潔優雅try-finally 需要顯式編寫異常處理代碼&#xff0c;更冗長 代碼復用性 上下文管理器可以封裝為類或函數&#xff0c;便于在多處復用try-finally 通常需要在每…

人體屬性識別+跌倒檢測:兒童行為監測與安全升級

智慧幼兒園的AI智能檢測盒應用實踐 背景&#xff1a;傳統園區管理的三大痛點 傳統幼兒園管理長期面臨三大核心挑戰&#xff1a;一是安全監控依賴人工巡查&#xff0c;存在視覺盲區與響應延遲&#xff0c;如某連鎖幼兒園曾因人工巡查疏漏&#xff0c;導致3起兒童跌倒事故未能及…

【ESP32-IDF筆記】09-UART配置和使用

環境配置 Visual Studio Code &#xff1a;版本1.98.2 ESP32&#xff1a;ESP32-S3 ESP-IDF&#xff1a;V5.4 支持型號&#xff1a;ESP32、ESP32-C2、ESP32-C3、ESP32-C5、ESP32-C6、ESP32-C61、ESP32-H2、ESP32-P4、 ESP32-S2、ESP32-S3 簡介 通用異步接收器/發送器 (UART) …

在 .NET Core 和 React 中使用 WebSockets 和 SignalR 進行實時數據傳輸

對于需要即時更新和通知的應用程序來說&#xff0c;實時數據傳輸至關重要。在 .NET Core 中&#xff0c;WebSocket 和 SignalR 提供了強大的工具來實現客戶端和服務器之間的實時通信。在本指南中&#xff0c;我們將探討如何在 .NET Core 應用程序中使用 WebSocket 和 SignalR 實…

第八十六篇 大數據排序算法:從廚房整理到分布式排序的智慧

目錄一、基礎排序算法&#xff1a;生活場景中的計算智慧1.1 冒泡排序&#xff1a;圖書館的書籍整理1.2 插入排序&#xff1a;廚房調料的整理藝術二、高效排序算法&#xff1a;大數據處理的利器2.1 快速排序&#xff1a;音樂APP的智能歌單2.2 歸并排序&#xff1a;學校成績單的合…

開源 | V3.1.1慧知開源重卡運營充電樁平臺 - 重卡運營充電樁平臺管理解決方案;企業級完整代碼 多租戶、模擬器、多運營商、多小程序;

【開源免費版】推薦一套企業級開源充電樁平臺&#xff1a;完整代碼包含多租戶、硬件模擬器、多運營商、多小程序&#xff0c;汽車 電動自行車、云快充協議&#xff1b;——(慧哥)慧知開源充電樁平臺&#xff1b;https://liwenhui.blog.csdn.net/article/details/148242725?spm…

ONLYOFFICE 協作空間 企業版使用秘籍-8.使用虛擬數據房間,處理機密文檔更安全

在當今快節奏的社會中&#xff0c;信息已成為極其關鍵的資源&#xff0c;因此&#xff0c;保護敏感數據至關重要。ONLYOFFICE 協作空間中的虛擬數據房間&#xff08;VDR&#xff09;提供了一個安全便捷的工作空間&#xff0c;確保文檔受到嚴密保護的同時&#xff0c;也能實現輕…

系統架構設計師論文分享-論軟件架構復用

我的軟考歷程 摘要 2023年2月&#xff0c;我所在的公司通過了研發紗線MES系統的立項&#xff0c;該項目為國內紗線工廠提供SAAS服務&#xff0c;旨在提升紗線工廠的數字化和智能化水平。我在該項目中擔任架構設計師&#xff0c;負責該項目的架構設計工作。本文結合我在該項目…

虛擬主機與獨立服務器如何選擇

在搭建和維護網站時&#xff0c;選擇合適的服務器套餐至關重要。虛擬主機和獨立服務器是兩種常見的選擇&#xff0c;它們各有優缺點&#xff0c;適用于不同需求的用戶。本文將深入探討這兩種服務器類型的特點&#xff0c;以幫助您為您的網站選擇最合適的服務器解決方案。虛擬主…

NFC的安全技術體系

NFC&#xff08;近場通信&#xff09;技術因廣泛應用于移動支付、身份認證、門禁控制等敏感場景&#xff0c;其安全技術體系是保障用戶數據與交易安全的核心。該體系涵蓋數據傳輸安全、存儲安全、身份認證、防攻擊機制等多個維度&#xff0c;通過硬件隔離、加密算法、協議規范等…

Echarts3D柱狀圖-圓柱體-文字在柱體上垂直顯示的實現方法

全部代碼 <!DOCTYPE html> <html lang"en" style"height: 100%"> <head><meta charset"utf-8"><title>3D柱狀圖-圓柱體-文字豎排</title> </head> <body style"height: 100%; margin: 0"…

【算法訓練營Day08】字符串part2

文章目錄 反轉字符串里的單詞右旋字符串KMP算法雙指針法總結 反轉字符串里的單詞 題目鏈接&#xff1a;151. 反轉字符串中的單詞 雙指針法解題邏輯 head指針遍歷字符串遍歷到單詞首單詞&#xff0c;生成end指針移動到單詞尾部遇到完整單詞收集&#xff0c;壓入棧中head指針移動…

如何使用backtrace定位Linux程序的崩潰位置

在嵌入式Linux開發中&#xff0c;特別是復雜軟件&#xff0c;多人協作開發時&#xff0c;當某人無意間寫了一個代碼bug導致程序崩潰&#xff0c;但又不知道崩潰的具體位置時&#xff0c;單純靠走讀代碼&#xff0c;很難快速的定位問題。 本篇就來介紹一種方法&#xff0c;使用…

十大排序算法匯總

好的&#xff0c;下面為你整理一篇面試全覆蓋、極其深入的十大排序算法總結博客&#xff0c;涵蓋算法原理、復雜度、穩定性、應用場景、工程實踐、C與Python實現&#xff08;含詳細注釋&#xff09;&#xff0c;并對比分析各種排序的優缺點與適用情境。內容力求結構清晰、講解透…

零基礎 “入坑” Java--- 七、數組(二)

文章目錄 一、數組轉字符串二、數組的拷貝三、求數組中元素的平均值四、查找數組中指定元素&#xff08;順序查找&#xff09;五、數組排序&#xff08;冒泡排序&#xff09;六、查找數組中指定元素&#xff08;二分查找&#xff09;七、判斷兩個數組中的元素是否相等八、填充數…