FileSystemFileHandle: createSyncAccessHandle() 方法
注意:此功能僅在 專用 Web Worker 中可用。
FileSystemFileHandle 介面的 createSyncAccessHandle() 方法返回一個 Promise,該 Promise 解析為一個 FileSystemSyncAccessHandle 物件,可用於同步地讀取和寫入檔案。此方法的同步性帶來了效能優勢,但它只能在專用 Web Worker 中用於 源私有檔案系統 內的檔案。
建立 FileSystemSyncAccessHandle 會對與檔案控制代碼關聯的檔案進行獨佔鎖定。這會阻止在現有訪問控制代碼關閉之前為該檔案建立進一步的 FileSystemSyncAccessHandle 或 FileSystemWritableFileStream。
語法
createSyncAccessHandle()
createSyncAccessHandle(options)
引數
options可選-
具有以下屬性的物件:
mode可選 非標準-
一個字串,指定訪問控制代碼的鎖定模式。預設值為
"readwrite"。可能的值為:"read-only"-
可以在檔案上同時開啟多個
FileSystemSyncAccessHandle物件(例如,當在多個標籤頁中使用同一應用程式時),前提是它們都以"read-only"模式開啟。一旦開啟,就可以在控制代碼上呼叫類似讀取的方法 —read()、getSize()和close()。 "readwrite"-
在一個檔案上只能開啟一個
FileSystemSyncAccessHandle物件。嘗試在第一個控制代碼關閉前開啟後續控制代碼將導致丟擲NoModificationAllowedError異常。一旦開啟,就可以在控制代碼上呼叫任何可用方法。 "readwrite-unsafe"-
可以在檔案上同時開啟多個
FileSystemSyncAccessHandle物件,前提是它們都以"readwrite-unsafe"模式開啟。一旦開啟,就可以在控制代碼上呼叫任何可用方法。
返回值
一個 Promise,它解析為一個 FileSystemSyncAccessHandle 物件。
異常
NotAllowedErrorDOMException-
如果控制代碼的
PermissionStatus.state在readwrite模式下不是granted,則丟擲此異常。 InvalidStateErrorDOMException-
如果
FileSystemSyncAccessHandle物件不代表 源私有檔案系統 中的檔案,則丟擲此異常。 NotFoundErrorDOMException-
如果當前條目未找到,則丟擲此異常。
NoModificationAllowedErrorDOMException-
如果瀏覽器無法獲取與檔案控制代碼關聯檔案的鎖定,則丟擲此異常。這可能是因為
mode設定為readwrite,並且嘗試同時開啟多個控制代碼。
示例
基本用法
以下非同步事件處理函式包含在 Web Worker 中。其中的程式碼片段會建立一個同步檔案訪問控制代碼。
onmessage = async (e) => {
// Retrieve message sent to work from main script
const message = e.data;
// Get handle to draft file
const root = await navigator.storage.getDirectory();
const draftHandle = await root.getFileHandle("draft.txt", { create: true });
// Get sync access handle
const accessHandle = await draftHandle.createSyncAccessHandle();
// …
// Always close FileSystemSyncAccessHandle if done.
accessHandle.close();
};
包含 mode 選項的完整示例
我們的 createSyncAccessHandle() 模式測試 示例(請參閱 原始碼)提供了一個 <input> 欄位用於輸入文字,以及兩個按鈕 — 一個用於將輸入的文字寫入源私有檔案系統的檔案末尾,另一個用於在檔案變得太滿時清空檔案。
嘗試探索上面的演示,並開啟瀏覽器開發者控制檯,以便您可以看到正在發生的事情。如果您嘗試在多個瀏覽器標籤頁中開啟演示,您會發現可以同時開啟多個控制代碼來寫入檔案。這是因為 createSyncAccessHandle() 呼叫上設定了 mode: "readwrite-unsafe"。
下面我們將深入探討程式碼。
HTML
兩個 <button> 元素和文字 <input> 欄位如下所示:
<ol>
<li>
<label for="file-text">Enter text to write to the file:</label>
<input type="text" id="file-text" name="file-text" />
</li>
<li>
Write your text to the file: <button class="write">Write text</button>
</li>
<li>
Empty the file if it gets too full:
<button class="empty">Empty file</button>
</li>
</ol>
主 JavaScript
HTML 檔案中的主執行緒 JavaScript 如下所示。我們獲取寫入文字按鈕、清空檔案按鈕和文字輸入欄位的引用,然後使用 Worker() 建構函式建立一個新的 Web Worker。然後,我們定義兩個函式並將它們設定為按鈕的事件處理程式。
- 當點選寫入文字按鈕時,會執行
writeToOPFS()。此函式使用Worker.postMessage()方法將文字欄位的輸入值作為物件傳送到 Worker,然後清空文字欄位,為下一次新增做好準備。請注意,傳遞的物件還包括一個command: "write"屬性,用於指定我們要透過此訊息觸發寫入操作。 - 當點選清空檔案按鈕時,會執行
emptyOPFS()。此函式將包含command: "empty"屬性的物件傳送到 Worker,指定要清空檔案。
const writeBtn = document.querySelector(".write");
const emptyBtn = document.querySelector(".empty");
const fileText = document.querySelector("#file-text");
const opfsWorker = new Worker("worker.js");
function writeToOPFS() {
opfsWorker.postMessage({
command: "write",
content: fileText.value,
});
console.log("Main script: Text posted to worker");
fileText.value = "";
}
function emptyOPFS() {
opfsWorker.postMessage({
command: "empty",
});
}
writeBtn.addEventListener("click", writeToOPFS);
emptyBtn.addEventListener("click", emptyOPFS);
Worker JavaScript
Worker JavaScript 如下所示。
首先,我們執行一個名為 initOPFS() 的函式,該函式使用 StorageManager.getDirectory() 獲取對 OPFS 根目錄的引用,使用 FileSystemDirectoryHandle.getFileHandle() 建立一個檔案並返回其控制代碼,然後使用 createSyncAccessHandle() 返回一個 FileSystemSyncAccessHandle。此呼叫包括 mode: "readwrite-unsafe" 屬性,允許多個控制代碼同時訪問同一檔案。
let accessHandle;
async function initOPFS() {
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle("file.txt", { create: true });
accessHandle = await fileHandle.createSyncAccessHandle({
mode: "readwrite-unsafe",
});
}
initOPFS();
在 Worker 的 訊息事件 處理函式中,我們首先使用 getSize() 獲取檔案的大小。然後,我們檢查傳送到訊息的資料是否包含 command 屬性值 "empty"。如果是,我們使用 truncate() 並將值設定為 0 來清空檔案,並更新 size 變數中包含的檔案大小。
如果訊息資料是其他內容,我們則
- 建立一個新的
TextEncoder和TextDecoder,以便稍後處理文字內容的編碼和解碼。 - 編碼訊息資料,並使用
write()將結果寫入檔案末尾,然後更新size變數中包含的檔案大小。 - 建立一個
DataView來包含檔案內容,並使用read()將內容讀取到其中。 - 解碼
DataView內容並將其記錄到控制檯。
onmessage = function (e) {
console.log("Worker: Message received from main script");
// Get the current size of the file
let size = accessHandle.getSize();
if (e.data.command === "empty") {
// Truncate the file to 0 bytes
accessHandle.truncate(0);
// Get the current size of the file
size = accessHandle.getSize();
} else {
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
// Encode content to write to the file
const content = textEncoder.encode(e.data.content);
// Write the content at the end of the file
accessHandle.write(content, { at: size });
// Get the current size of the file
size = accessHandle.getSize();
// Prepare a data view of the length of the file
const dataView = new DataView(new ArrayBuffer(size));
// Read the entire file into the data view
accessHandle.read(dataView, { at: 0 });
// Log the current file contents to the console
console.log(`File contents: ${textDecoder.decode(dataView)}`);
// Flush the changes
accessHandle.flush();
}
// Log the size of the file to the console
console.log(`Size: ${size}`);
};
規範
| 規範 |
|---|
| 檔案系統 # api-filesystemfilehandle-createsyncaccesshandle |
瀏覽器相容性
載入中…