食譜

此頁面收集了實現常見應用程式層級功能的「食譜」和技巧,例如...

匯入和匯出資料庫

一個常用的功能是上傳和下載資料庫。

將瀏覽器內資料庫匯出到本機檔案系統

下載很簡單,只要開啟資料庫控制代碼即可輕鬆實現。取得資料庫的原始位元組是第一步(也是最簡單的一步)

const byteArray = sqlite3.capi.sqlite3_js_db_export(myDb);

然後,我們需要更多程式碼才能將該位元組陣列匯出瀏覽器。以下是一種方法

const blob = new Blob([byteArray.buffer],
                      {type:"application/x-sqlite3"});
const a = document.createElement('a');
document.body.appendChild(a);
a.href = window.URL.createObjectURL(blob);
a.download = (myDb.filename.split('/').pop() || "my.sqlite3");
a.addEventListener('click',function(){
  setTimeout(function(){
    console.log("Exported (possibly auto-downloaded) database");
    window.URL.revokeObjectURL(a.href);
    a.remove();
  },500);
});
a.click();

將資料庫匯入瀏覽器

預先警告:這不適用於 WAL 模式資料庫。 WASM 環境缺少 WASM 所需的共享記憶體 API,因此 WASM 組建無法讀取 WAL 模式資料庫。

將資料庫匯入瀏覽器比匯出更棘手,因為用戶端必須能夠將資料庫儲存在某處,而此類儲存空間取決於 sqlite3_vfs。第一步,取得資料庫位元組,相當通用,以下將示範兩種方法。

首先,我們將展示如何將本機資料庫檔案上傳到瀏覽器。為此,我們需要一個用於擷取資料庫的 UI 元素

<input type='file' id='load-db'/>

然後,我們需要監聽將上傳檔案傳輸到我們的 JS 程式碼的事件。忽略載入進度指示器等細節,看起來像...

const eUploadDb = document.querySelector('#load-db');
eUploadDb.addEventListener('change',function(){
  const f = this.files[0];
  if(!f) return;
  const r = new FileReader();
  r.addEventListener('load', function(){
    // this.result is an ArrayBuffer with the file's contents
  });
  r.readAsArrayBuffer(f);
});

同樣地,可以使用 fetch() 從本機網路伺服器或遠端網路伺服器載入資料庫

fetch( '...url to the db...' )
  .then(res=>res.arrayBuffer)
  .then(function(arrayBuffer){
    // the database's bytes are in arrayBuffer
  });

載入該 ArrayBuffer 後,我們需要決定如何處理它。我們至少有兩個選項。最簡單的方法是將其載入到記憶體資料庫中

// assuming arrayBuffer contains the result of the above operation...
const p = sqlite3.wasm.allocFromTypedArray(arrayBuffer);
const db = new sqlite3.oo1.DB();
const rc = sqlite3.capi.sqlite3_deserialize(
  db.pointer, 'main', p, arrayBuffer.byteLength, arrayBuffer.byteLength,
  sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE
  // Optionally:
  // | sqlite3.capi.SQLITE_DESERIALIZE_RESIZEABLE
);
db.checkRc(rc);

由於 sqlite3_deserialize() 的文件 中討論的原因,sqlite3_deserialize() 的最後一個參數在此很重要。

擷取的資料庫可以寫入瀏覽器端儲存空間,但具體如何操作取決於 VFS

替換函式庫的記錄例程

為了幫助支援函式庫的人從報告問題的使用者那裡收集詳細資訊,它可能會將少量資訊記錄到 JS 開發控制台。透過使用與 console.log() 函數系列相容的例程替換記錄例程,可以使其完全靜默。要在載入函式庫之前安裝這些例程,請執行

globalThis.sqlite3ApiConfig = {
  // define any or all of these:
  warn: ()=>{},
  error: ()=>{},
  debug: ()=>{},
  log: ()=>{}
};
// Then load the library using your preferred approach, then
// delete the temporary config object:
delete globalThis.sqlite3ApiConfig /* automatically done as of 3.46.0 */;

這些例程必須與 console.log() 介面相容,但函式庫不依賴它們實際如何處理其參數,因此省略它們或將它們傳送到替代記錄通道都是合法的選項。它們不得拋出任何例外,否則函式庫可能會發生錯誤。

這些設定在函式庫載入後仍可修改,但它們可能已在函式庫初始化階段發出輸出,例如在 OPFS 不可用時發出警告,因此修改設定將無法阻止所有可能的輸出。

sqlite3.config.log =
  sqlite3.config.error =
  sqlite3.config.warn =
  sqlite3.config.debug = ()=>{};

請注意,覆寫_所有_設定並非必要。截至目前,函式庫僅在少數情況下會發出警告,在極少數情況下會發出錯誤,但除了開發階段之外,不應發出 log()debug() 訊息。