FileSystemFileHandle: phương thức createSyncAccessHandle()
Baseline
Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2023.
Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.
Note: This feature is only available in Dedicated Web Workers.
Phương thức createSyncAccessHandle() của giao diện FileSystemFileHandle trả về một Promise được thực thi thành một đối tượng FileSystemSyncAccessHandle có thể dùng để đọc và ghi file đồng bộ. Tính đồng bộ của phương thức này mang lại lợi thế về hiệu năng, nhưng nó chỉ có thể dùng bên trong các Web Worker chuyên dụng cho các tệp nằm trong origin private file system.
Việc tạo một FileSystemSyncAccessHandle sẽ lấy một khóa độc quyền trên file liên kết với file handle. Điều này ngăn việc tạo thêm các FileSystemSyncAccessHandle hoặc FileSystemWritableFileStream cho file đó cho đến khi access handle hiện có được đóng.
Cú pháp
createSyncAccessHandle()
createSyncAccessHandle(options)
Tham số
optionsOptional-
Một object với các thuộc tính sau:
modeOptional Non-standard-
Một chuỗi chỉ định chế độ khóa cho access handle. Giá trị mặc định là
"readwrite". Các giá trị có thể có là:"read-only"-
Có thể mở đồng thời nhiều đối tượng
FileSystemSyncAccessHandletrên cùng một file, miễn là tất cả đều mở ở chế độ"read-only". Sau khi mở, các phương thức kiểu đọc có thể được gọi trên handle —read(),getSize(), vàclose(). "readwrite"-
Chỉ có thể mở một đối tượng
FileSystemSyncAccessHandletrên một file. Cố mở các handle tiếp theo trước khi handle đầu tiên được đóng sẽ dẫn tới ngoại lệNoModificationAllowedError. "readwrite-unsafe"-
Có thể mở đồng thời nhiều đối tượng
FileSystemSyncAccessHandletrên cùng một file, miễn là tất cả đều mở ở chế độ"readwrite-unsafe". Sau khi mở, mọi phương thức khả dụng đều có thể được gọi trên các handle.
Giá trị trả về
Một Promise được thực thi thành một đối tượng FileSystemSyncAccessHandle.
Ngoại lệ
NotAllowedErrorDOMException-
Được ném ra nếu
PermissionStatus.statecủa handle không phải làgrantedở chế độreadwrite. InvalidStateErrorDOMException-
Được ném ra nếu đối tượng
FileSystemSyncAccessHandlekhông đại diện cho một file trong origin private file system. NotFoundErrorDOMException-
Được ném ra nếu mục hiện tại không được tìm thấy.
NoModificationAllowedErrorDOMException-
Được ném ra nếu trình duyệt không thể lấy khóa trên file liên kết với file handle. Điều này có thể xảy ra vì
modeđược đặt thànhreadwritevà có nỗ lực mở nhiều handle cùng lúc.
Ví dụ
>Cách dùng cơ bản
Hàm xử lý sự kiện bất đồng bộ sau nằm bên trong một Web Worker. Đoạn mã bên trong nó tạo ra một handle truy cập file đồng bộ.
onmessage = async (e) => {
// Lấy thông điệp được gửi tới worker từ script chính
const message = e.data;
// Lấy handle tới file nháp
const root = await navigator.storage.getDirectory();
const draftHandle = await root.getFileHandle("draft.txt", { create: true });
// Lấy sync access handle
const accessHandle = await draftHandle.createSyncAccessHandle();
// …
// Luôn đóng FileSystemSyncAccessHandle khi xong.
accessHandle.close();
};
Ví dụ đầy đủ với tùy chọn mode
Ví dụ createSyncAccessHandle() mode test của chúng tôi (xem mã nguồn) cung cấp một trường <input> để nhập văn bản, và hai nút — một nút để ghi văn bản đã nhập vào cuối file trong origin private file system, và một nút để làm trống file khi nó trở nên quá đầy.
Hãy thử xem demo ở trên, đồng thời mở bảng console của nhà phát triển trình duyệt để thấy điều gì đang xảy ra. Nếu bạn mở demo trong nhiều tab trình duyệt, bạn sẽ thấy nhiều handle có thể được mở cùng lúc để ghi vào file cùng lúc. Điều này là do mode: "readwrite-unsafe" được đặt trong các lời gọi createSyncAccessHandle().
Phía dưới chúng ta sẽ xem mã nguồn.
HTML
Hai phần tử <button> và trường văn bản <input> trông như sau:
<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 chính
Đoạn JavaScript ở luồng chính trong file HTML được hiển thị bên dưới. Chúng ta lấy tham chiếu tới nút ghi văn bản, nút làm trống file, và trường nhập văn bản, sau đó tạo một web worker mới bằng constructor Worker(). Sau đó chúng ta định nghĩa hai hàm và gán chúng làm trình xử lý sự kiện cho các nút:
writeToOPFS()chạy khi nút ghi văn bản được nhấn. Hàm này gửi giá trị đã nhập của trường văn bản tới worker trong một object bằng phương thứcWorker.postMessage(), rồi làm trống trường văn bản để sẵn sàng cho lần thêm tiếp theo. Lưu ý object được truyền cũng bao gồm thuộc tínhcommand: "write"để chỉ định rằng chúng ta muốn kích hoạt hành động ghi bằng thông điệp này.emptyOPFS()chạy khi nút làm trống file được nhấn. Hàm này gửi một object chứa thuộc tínhcommand: "empty"tới worker, chỉ định rằng file sẽ được làm trống.
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);
JavaScript của worker
JavaScript của worker được hiển thị bên dưới.
Đầu tiên, chúng ta chạy một hàm tên initOPFS() để lấy tham chiếu tới gốc OPFS bằng StorageManager.getDirectory(), tạo một file và trả về handle của nó bằng FileSystemDirectoryHandle.getFileHandle(), rồi trả về một FileSystemSyncAccessHandle bằng createSyncAccessHandle(). Lời gọi này bao gồm thuộc tính mode: "readwrite-unsafe", cho phép nhiều handle truy cập cùng một file đồng thời.
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();
Trong hàm xử lý sự kiện message của worker, trước tiên chúng ta lấy kích thước file bằng getSize(). Sau đó chúng ta kiểm tra xem dữ liệu gửi trong thông điệp có bao gồm giá trị thuộc tính command là "empty" hay không. Nếu có, chúng ta làm trống file bằng truncate() với giá trị 0, và cập nhật kích thước file lưu trong biến size.
Nếu dữ liệu thông điệp là thứ khác, chúng ta:
- Tạo một
TextEncodervàTextDecodermới để xử lý mã hóa và giải mã nội dung văn bản sau này. - Mã hóa dữ liệu thông điệp và ghi kết quả vào cuối file bằng
write(), rồi cập nhật kích thước file lưu trong biếnsize. - Tạo một
DataViewđể chứa nội dung file, và đọc nội dung vào đó bằngread(). - Giải mã nội dung
DataViewvà ghi nó ra console.
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}`);
};
Thông số kỹ thuật
| Specification |
|---|
| File System> # api-filesystemfilehandle-createsyncaccesshandle> |