Worker 能用同步 API,是因為它擋不住主執行緒
同步 I/O 在主執行緒是禁忌,因為它會卡住畫面。Web Worker 沒有這個問題——它本來就擋不到主執行緒,所以平台可以在那裡開放同步 API。
以 OPFS 為例,同一份儲存有兩套 API:
| 環境 | API | 取得方式 |
|---|---|---|
| 主執行緒 | 非同步(Promise) | createWritable() → write() → close() |
| Web Worker | 同步 | createSyncAccessHandle() → read() / write(),沒有 await |
為什麼要有同步版本
兩個理由,第二個才是真正的原因:
- 少掉 Promise 的開銷,比較快。
- 可編譯為 WebAssembly 的語言(C 之類),檔案作業本來就是同步的:
FILE *f;
f = fopen("example.txt", "w+");
fputs("Some text\n", f);
fclose(f);這種介面沒有放 callback 或 promise 的位置。所以要讓 SQLite 這類 C 程式在瀏覽器裡跑,同步 I/O 不是效能優化而是先決條件——見 OPFS sync access handle 讓 SQLite 能在瀏覽器只讀用得到的 page。
一個命名陷阱
儘管方法名稱裡有
Sync,createSyncAccessHandle()本身是非同步的;而且你是從一個「一般的」FileSystemFileHandle取得「同步的」FileSystemSyncAccessHandle。
Sync 形容的是「拿到之後怎麼操作」,不是「怎麼取得它」。
搬進 Worker 換到的不是資源
判準要記清楚:換到的是「同步 API + 不阻塞畫面」,不是「更多記憶體」——見 Worker 與分頁共用同一份記憶體配額。