setIntervalとは
一定の遅延間隔を置いて関数を繰り返し実行したいときに利用する関数。 ポーリングで利用することが多い。 参考 setInterval
1秒ごとにコンソール出力する例。
<!doctype html>
<html lang="ja">
<script>
window.setInterval(function(){
console.log("polling");
}, 1000);
</script>
<body>
</body>
</html>
setIntervalの生存期間
リファレンスに記載がないので、動作確認したところ以下のようになった。
参考 www.w3.org
参考 developer.mozilla.org
- DOMをunloadして次のDOMをloadするまで(=Documentオブジェクトと同じ生存期間)
- ページ内リンクやJSでの動的なDOM書き換え、は
setInterval
がクリアされない - ページ外リンク、は
setInterval
がクリアされる
WindowオブジェクトとDocumentオブジェクトの関係は以下を参考に。
参考 Window オブジェクトや Document オブジェクト、DOMなど
setIntervalの動作確認
- Google Chrome 60.0.3112.90
<!doctype html>
<html lang="ja">
<script>
window.onload = function () {
window.setInterval(function() { console.log("hi"); }, 1000);
document.getElementById('btn').addEventListener('click', function() {
var parent = document.getElementsByTagName('body')[0];
while(parent.firstChild) parent.removeChild(parent.firstChild);
var newElm = document.createElement('div');
newElm.textContent = 'hello world';
parent.appendChild(newElm);
});
}
</script>
<body>
<a href="#xxx">ページ内リンク</a>
<a href="other.html">ページ外リンク</a>
<button id="btn" type="button">JSで動的に書き替える</button>
<p>dummy</p>
...
<p>dummy</p>
<p id="xxx">xxx</p>
<p>dummy</p>
...
<p>dummy</p>
</body>
</html>
<!doctype html>
<html lang="ja">
<body>
<a href="polling.html">戻る</a>
</body>
</html>
Vue.jsでsetIntervalを使ってポーリングするときの注意点
SPAの場合、データのみリクエストしてDOMを差分更新することになる。そのため、Documentオブジェクトの入れ替えが起こらず、一度setIntervalしたタイマは、全画面で有効になり続ける。
検証
ポーリングしたいページ
<template>
<div>
<h1>polling</h1>
<router-link to="/goodbye">Goodbye</router-link>
</div>
</template>
<script>
export default {
name: 'hello',
mounted () {
setInterval(function () {
console.log('hi')
}, 1000)
}
}
</script>
ポーリングしたくないページ
<template>
<div>
<h1>ポーリングしたくないページ</h1>
</div>
</template>
<script>
export default {
name: 'boodbye'
}
</script>
問題点
ポーリングによる、無駄なネットワークコストがかかる。
解決方法
clearInterval
を利用して、タイマを削除する。
参考 (clearInterval)https://developer.mozilla.org/ja/docs/Web/API/WindowTimers/clearInterval
ページを遷移する際にclearIntervalを呼ぶためには、ライフサイクルフックを利用する。
参考 ライフサイクルフック
<template>
<div>
<h1>polling</h1>
<router-link to="/goodbye">Goodbye</router-link>
</div>
</template>
<script>
export default {
name: 'hello',
data: function () {
return {
intervalId: undefined
}
},
mounted () {
this.intervalId = setInterval(function () {
console.log('hi')
}, 1000)
},
beforeDestroy () {
console.log('clearInterval')
clearInterval(this.intervalId)
}
}
</script>
結論
Vue.js(というかSPA全般)でsetInterval
するときは、clearInterval
しよう。