1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Denoのwindow.close()の動作

Last updated at Posted at 2022-07-14

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()が同じものだと勘違いしていてデータを消し飛ばしました。みなさんも気を付けてください!

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?