disconnect()してるのに止まらない

MutationObserverは、DOMが変化したときにコールバック関数を実行する。コールバックの引数は2つで、第一引数がMutationRecordオブジェクトの入った配列、第二引数はコールバックを実行しているインスタンス。

この第一引数の配列をループで回すという使い方をよくするのだが、disconnect()してるのにループが止まらないという不具合に遭遇した。

いきなり結論を書いてしまうと、disconnect()した回でループを止めるには、breakreturnでループを抜ける必要がある。disconnect()はループを抜けるメソッドじゃないのだから、止まらなくても当たり前ではあるのだが、じゃあdisconnect()って何なんだ。DOMの監視をやめるメソッドじゃないのか。

MDNの該当ページを確認してみると、

すでに検知されているものの、まだオブザーバーに報告されていない変更の通知は、すべて破棄されます。

MutationObserver.disconnect()

と書いてある。自分の認識と相違なさそうな気がするんだけどなあ。それに、こういう仕様ならばループは止まってもよさそうである。

でも「検知」とか「報告」というワードがちと臭い感じもするな。とりあえず、第一引数の配列のlength値を観察してみた。

最初に書いたように、DOMが変化したときにコールバックが実行されているわけなので、ジェネレーターみたいにいっこいっこ処理してるイメージでいたのだけれど、なんか違うっぽい。要素数がバラバラなのだ。1つだったり、50とかあったりする。

なるほど。そりゃあdisconnect()しても止まらないわけだ。配列の要素が残ってるからな。

コールバック実行中に待たされてるMutationRecordを、次のコールバックでまとめて引き渡してる感じなんだろうか。disconnect()が発動すると、次のコールバックが実行されなくなり、待たされてるMutationRecordも必然的に破棄されると。でも現在処理中のループは最後の要素まで回る。

これ知らなかったのに今までよく不具合が起きなかったな……。

あと、ループで回さないと漏れが出るのではないかと心配していたのだが、そんなアホなこと気にする必要ないんだな。むしろループを使わない処理を真っ先に考えるべきだわ。

お知らせ

現在お知らせはありません。

最近の投稿

シェア