nextTickと非同期のライフサイクルの実行順序(Nuxt 3)
投稿日:2025/11/26
- 実務のプロジェクトではNuxt 3のnextTickが多用されており、その際に非同期のライフサイクルが使用されていた場合に意図したとおりにnextTickが実行されなかったので自身の備忘録として記載しています。
- ライフサイクルのcreated内でAPI(非同期処理)でデータを取得することはよくあると思います。この場合は非同期処理にawaitをつけてcreatadにasyncを付けますがその際にmountedにあるnextTickがcreatedの処理の完了を待たずして実行されます。
- 実例として以下のようなコードになっており、mountedにあるnextTick内のコンソールログがcreated内のコンソールログよりも先に実行します。その結果コンソールにはB→Aの順で表示されます。
// foo.vue
<script lang="ts">
import { defineComponent, nextTick } from 'vue'
export default defineComponent({
async created() {
// 1秒停止
await new Promise(resolve => {
setTimeout(resolve, 1000)
})
console.log('A')
},
mounted() {
nextTick(() => {
// console.log('A')よりもconsole.log('B')が先に実行される
console.log('B')
})
}
})
</script>- チーム内ではnextTickは必ずDOM更新が完了した際に実行される(DOM更新が完了 = createdが完了している)と認識していたので当時はなぜこのような事象が起きたか分かりませんでした。
- 調査した結果、以下の原因により上記事象が発生していたことがわかりました。
- created自体にasyncが付いているので非同期処理となり、created内の処理を待たずしてDOMが生成される。
- そのためmoutendが実行され、DOMの更新が完了したタイミングでnextTickが実行される。
- 結果としてcreatedの処理の完了前にnextTick内の処理が実行されることとなる。
ライフサイクル(created)と非同期処理が組み合わさった時の挙動をなあなあにしていたので、今回良い勉強になりました。