Vue.jsで定期的な処理の実行を目的として、setInetervalメソッドを使用したときに処理が止まらなくなるというミスに出くわしましたので、setInetervalを利用するときの注意点と今回の事象と対策を紹介していきます。
SetIntervalが止まらない
SetIntervalを利用して、特定のダイアログコンポーネントを開いている間は、定期的にAPIを叩くという処理を作成しました。
SetInterval関数でよく見かける記載方法は以下の通りです。
setInterval(() => {
// 実行したい処理
this.getAPI();
}, 5000);
}
今回は、ダイアログコンポーネントを作成しており、そのダイアログを開いている間は、getAPI()の処理を繰り返すこととして、想定していました。
しかし、実際には、ダイアログコンポーネントを閉じても、このSetIntervalが止まっておらず、getAPI()の処理が動き続けています。
さらに、この状態で、同じダイアログコンポーネントを利用した他のダイアログを開くと、SetIneterValの動作がそれぞれ二重に処理されてします。
今回作成しているのはタスク管理アプリで、タスクをクリックしたときに、その詳細が表示するダイアログでしたので、一度タスクを開いたときのSetIntervalが次のタスクを開いたときにもまだ処理を続けてしまうので、5秒ごとの実行処理が重複してしまいます。
次にタスクを開いても、内容が5秒後ごとに前開いていたタスクの情報に切り替わってしまうという致命的なバグです。
ライフサイクルの理解と変数化
そこで、一度実行したSetIntervalを停止する処理を実行する必要があります。
Vue.jsなどであれば、コンポーネントを閉じたとて、その処理は実行されたままです。
そこで、SetIntervalの変数への代入とコンポーネントを閉じるときに、その変数を停止させる必要があります。
<script>
const interval = ref()
const onMounted = () => {
interval.value = setInterval(() => {
this.getAPI();
}, 5000);
}
}
const beforeUnmount = () => {
if(interval.value){
clearInterval(interval.value);
}
}
</script>
vue.jsで、リアクティブとして定義する変数に関数を代入するという発想を持てていませんでした。
あくまで、template
で使うための、値やデータをいれるものという固定概念があったように思います。
onMounted
(Vue2ではmoutend)のライフサイクルで、SetInterval関数を実行して、その所jリをintevalに代入します。
次に、コンポーネントが崩れるときとして、beforeUnmount
(Vue2ではboforeDestroy)のライフサイクルでClearInterval()の引数にSetIntervalを与え、処理をストップさせます。
これで、コンポーネントが閉じる直前に、処理が止められ、次のタスクを開くときには新たなonMountによるSetInterval関数が実行となります。
おわりに
考えてみれば、当たり前ですし、ClearIntervalで止める必要があることは理解していいました。
ただ、関数をリアクティブな値に代入して、beforeUnmoutのライフサイクルで呼び出すという発想が持ててなかったです。
なんてないと思っていたところで、躓きやすいので無事解決できてよかった。
コメント