Denoにはブラウザ互換のwindow.close()
が実装されています。
この関数は、呼ばれると直ちに処理を終了するものと思っていたのですが、そういうわけではないようです。
本記事ではDenoにおけるwindow.close()
の挙動を確認します。
なお、
window.close()
globalThis.close()
close()
は全て同等の記述ですが、本記事ではwindow.close()
に書き方を統一します。
Denoにおけるwindow.close()
の動作
window.close()
を呼んでも直ちに処理は終了せず、タスクキューとマイクロタスクキューを消化してから処理を終了します。
タスクキューとマイクロタスクキューはPromiseやsetTimeoutなどによって発行されるタスクを管理するものです。詳しくはこちらの記事が参考になります。
具体例を見てみましょう。
まず、window.close()
を呼んでも、後続の処理は普通に実行されます。
console.log(0); // 実行される
window.close();
console.log(1); // 実行される
更に、setTimeout(fn, 0)
やqueueMicrotask(fn)
やPromise
を用いてコールバックに設定したタスク or マイクロタスクも、window.close
後に実行されます。
console.log(0); // 実行される
window.close();
console.log(1); // 実行される
queueMicrotask(() => {
console.log(3); // 実行される
});
setTimeout(() => {
console.log(5); // 実行される
}, 0);
new Promise<void>((resolve) => {
console.log(2); // 実行される
resolve();
}).then(() => {
console.log(4); // 実行される
});
一方、setTimeout(fn, 1)
やfetch(url)
の後続の処理などは実行されません。これは、タスクキューやマイクロタスクキューがいったん空になり、そこでプロセスが終了されるためです。
console.log(0); // 実行される
window.close();
setTimeout(() => {
console.log(2); // 実行されない!
}, 1); // <- ここが1以上なのがポイント
console.log(1); // 実行される
console.log(0); // 実行される
window.close();
fetch("https://google.com").then(() => {
console.log(1); // 実行されない!
});
ただし、後続の処理の内容によってはsetTimeoutで指定した秒数が経過してしまうので、setTimeoutの中身が実行される可能性があります。
console.log(0); // 実行される
window.close();
setTimeout(() => {
console.log(2); // 実行される
}, 1);
console.log(1); // 実行される
for (let i = 0; i < 100000; i++); // ※この行を実行している間に1ミリ秒経過する
↑の挙動、タイミングによっては実行されたりされなかったりするという挙動が発生する可能性があり、バグの原因になりそうだなと思いました(感想)。
雑な理解としては、
-
setTimeout(fn, 0)
は実行される -
await
以降は実行されない
みたいな感じでいいのではないかと思います。(厳密には間違っています!)
処理を終了するならDeno.exit()
上で解説したように、window.close()
はブラウザ互換になるように作られていて、単純に処理を止めたい時に使うのは難しそうです。
単純に処理を止めたい場合、Deno.exit()
を使います。この関数が呼ばれると直ちにプロセスが終了します。後続の処理は実行されません。
console.log(0); // 実行される
Deno.exit();
console.log(1); // 実行されない
引数には終了コードを渡すことができます。
まとめ
- Denoの
window.close()
は後続の処理を実行してタスクキュー/マイクロタスクキューを空にしてから終了する。 - 単に処理を止めたいときは
Deno.exit()
を使う。
私はDeno.exit()
とwindow.close()
が同じものだと勘違いしていてデータを消し飛ばしました。みなさんも気を付けてください!
参考文献
-
window.close()
の仕様書 https://html.spec.whatwg.org/multipage/window-object.html#dom-window-close