Deno | Manual
ここ
DenoでWorkerを使うときはnew Worker
の第二引数で{type: "module"}
をつける。
Workerの中でDenoの機能を使いたいときはさらにdeno
プロパティを追加する。
deno: true
, deno: false
でもいいらしい。
で、実行時は--allow-read
と--unstable
をつける。
const worker = new Worker(new URL("./worker.js", import.meta.url).href, {
type: "module",
deno: {
namespace: true,
},
});
worker.postMessage({ filename: "./log.txt" });
self.onmessage = async (e) => {
const { filename } = e.data;
const text = await Deno.readTextFile(filename);
console.log(text);
self.close();
};
hello world
だけどエラーが出た。
やってみてエラー出なかった人もいると思う。
% deno run --allow-read --unstable main.js
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
Workerのエラーは何も教えてくれないから困った。
エラーの理由
ソースと同じディレクトリにlog.txt
を置いて読もうとしてたこと。
log.txt
がカレントディレクトリにないと動かない。
./worker.js
と./log.txt
という、二つの相対パスが書かれてる。
./worker.js
はnew URL("./worker.js", import.meta.url).href
で絶対パスに変換されてる。
ソースと同じディレクトリにあればいい。
だけど./log.txt
は相対パス。
今いるフォルダの中にlog.txt
がないとDeno.readTextFile
で読めない。
じゃぁ絶対パスにすればいいかってnew URL("./log.txt", import.meta.url).href
を渡しても動かない。
URL#hrefが返すパスはfile://
から始まるので、取り除いておかないとDeno.readFile
で読めない。
標準ライブラリのfromFileUrl
を使う。正規表現で消してもいいけど。
つまりmain.js
をこうすればいけた。
カレントディレクトリのテキストファイルを読みたい人はそのままでいい。
import { fromFileUrl } from "https://deno.land/std@0.101.0/path/mod.ts";
const workerURL = new URL("./worker.js", import.meta.url).href;
const textURL = new URL("./log.txt", import.meta.url).href; // file:///path/to/log.txt
const filename = fromFileUrl(textURL); // /path/to/log.txt
const worker = new Worker(workerURL, {
type: "module",
deno: {
namespace: true,
},
});
worker.postMessage({ filename });
ちなみにmain.js側から引き継ぐパーミッションも個別に指定できるけど、そっちはソースディレクトリからの相対パスになる。
import { fromFileUrl } from "https://deno.land/std@0.101.0/path/mod.ts";
const workerURL = new URL("./worker.js", import.meta.url).href;
const textURL = new URL("./log.txt", import.meta.url).href;
const filename = fromFileUrl(textURL);
const worker = new Worker(workerURL, {
type: "module",
deno: {
namespace: true,
permissions: {
read: [
"./log.txt", // main.jsからの相対パス!
],
},
},
});
worker.postMessage({ filename });
分かってみれば、そりゃDeno.readTextFileはカレントディレクトリ読むよねって感じ