Nuxt.jsで開発をしており、
setIntervalで定期的にapi通信をするように書いていました。
そして、beforeDestroyにclearInterval書いてるのに、違うページに遷移したあとも、apiが呼ばれ続けている???
という現象に遭遇しました。
先に解決策を
setIntervalを、mountedではなくcreatedに書きました。
※これで本当に解決出来たのか確信がないです。わかる方いたら教えてください。m(_ _)m
export default {
data() {
return {
intervalId: null,
};
},
created() {
this.intervalId = setInterval(async () => {
// api通信の記述
}, 10000);
},
beforeDestroy() {
clearInterval(this.intervalId);
},
}
何が起きていて、どうしたのか
まず、beforeDestroyのclearInterval自体は、クリアしたりクリアしていなかったりで、必ずクリアされないというわけではありませんでした。
再現方法を探っていくうちに、そのページにアクセスして、すぐに違うページにアクセスするとクリアされないことがある、ということがわかりました。
修正前のsetIntervalは、mountedに書いていました。
また、そもそも設計が良くないのかもしれないですが・・
このsetIntervalでアクセスするapiは、その前にapiで取得したデータの一部をパラメーターに渡す必要があり、
mounted
↓
api通信
↓
setIntervalで定期的なapi通信開始
という手順の処理でした。
各処理の開始や終了などにコンソールを入れ、いろいろみてみると、
なんと、mountedの処理が完了する前にbeforeDestroyが呼ばれるときもあり、その後のmountedの処理は中断されることなく実行していました。
(beforeDestroyのclearIntervalの処理が行われたあと、setIntervalの処理が行われidが付与されていたので、setIntervalはクリアされていなかった)
なるほど、
Vue.jsのライフサイクル関連で、そのようなことが書いてあるものは見かけたことがなかったのでそういう可能性というのを考えていませんでしたが、そういうことなのでしょう。
上記では、createdに移動することで解決したと書きましたが、mountedのawaitの処理より先に書くのでも、良いかもしれません。
ただ、
mountedの処理が完了する前にbeforeDestroyが呼ばれる場合がある(処理は中断されない)、というのはわかりましたが、
createdの処理が必ずbeforeDestroyより先に行われるのか、というのがわかっていません。
そう考えると、intervalIdはページ内で持たないほうが良いのか?
storeを活用すべき?
でしょうか?
mountedに処理を書いていたとき、違うページに遷移したあとにも実行され続けているsetIntervalをクリアする方法はなく、、ブラウザを閉じたり画面を更新するまでずっと呼ばれ続けるっぽいです。
そこそこ調べましたが、この辺りについて書いている記事は見つからず、何が最適なのかはわかっていません。