Nuxt中如何在初始fetch和所有Ad组件mounted完成后发起新fetch请求
实现方案
核心思路是把两个前置条件都封装为可监听的异步状态,等待两个状态同时满足后再触发广告请求,具体实现步骤如下:
步骤1:改造Vuex状态管理,添加就绪状态标识
首先在广告相关的store模块中新增计数和就绪状态,用来追踪所有Ad组件的action执行进度,以及resourceId的获取状态:
// store/ads.js export const state = () => ({ // 原有存储广告参数的数组 adParams: [], // 所有Ad组件参数是否全部存入完成 adConfigReady: false, // 正在执行中的存参action数量 pendingAdActions: 0, // 页面fetch返回的资源ID resourceId: null, // resourceId是否获取完成 resourceIdReady: false }) export const mutations = { ADD_AD_PARAM(state, param) { state.adParams.push(param) }, INCREASE_PENDING(state) { state.pendingAdActions++ state.adConfigReady = false }, DECREASE_PENDING(state) { state.pendingAdActions-- if (state.pendingAdActions === 0) { state.adConfigReady = true } }, SET_RESOURCE_ID(state, id) { state.resourceId = id state.resourceIdReady = true } } export const actions = { // Ad组件调用的存参action async saveAdParam({ commit }, { section, adId }) { commit('INCREASE_PENDING') try { // 原有存参逻辑保持不变 commit('ADD_AD_PARAM', { section, adId }) } finally { commit('DECREASE_PENDING') } }, // 页面fetch调用的保存resourceId的action async saveResourceId({ commit }, resourceId) { commit('SET_RESOURCE_ID', resourceId) } }
步骤2:改造页面fetch钩子,存入resourceId
// 页面组件(Nuxt2示例) export default { async fetch({ store }) { // 原有页面资源请求逻辑保持不变 const res = await fetch('/api/your-resource-endpoint') const { resourceId } = await res.json() // 存入store更新就绪状态 await store.dispatch('ads/saveResourceId', resourceId) } }
步骤3:保持Ad组件逻辑不变
Ad组件挂载时继续调用原有的saveAdParam action即可,新增的计数逻辑已经封装在action内部,无需修改组件原有代码。
步骤4:等待双条件满足后发起广告请求
通过Promise.all封装两个就绪条件的监听逻辑,保证两个前置任务都完成后再执行请求:
// 页面组件 import { mapState } from 'vuex' export default { computed: { ...mapState('ads', ['adConfigReady', 'resourceIdReady', 'adParams', 'resourceId']) }, data() { return { // 避免重复请求的标志位 adsFetched: false } }, async mounted() { if (this.adsFetched) return // 封装resourceId就绪的Promise const waitForResourceId = new Promise(resolve => { if (this.resourceIdReady) return resolve(this.resourceId) const unwatch = this.$watch('resourceIdReady', isReady => { if (isReady) { unwatch() resolve(this.resourceId) } }) }) // 封装广告配置就绪的Promise const waitForAdConfig = new Promise(resolve => { if (this.adConfigReady) return resolve(this.adParams) const unwatch = this.$watch('adConfigReady', isReady => { if (isReady) { unwatch() resolve(this.adParams) } }) }) // 等待两个前置条件都满足 const [adParams, resourceId] = await Promise.all([waitForAdConfig, waitForResourceId]) // 生成你的配置对象 const adConfig = adParams.reduce((prev, curr) => { prev[curr.section] = curr.adId return prev }, {}) // 发起广告请求 await fetchAds(adConfig, resourceId) this.adsFetched = true } }
注意事项
- 如果存在动态渲染的Ad组件(通过
v-if/v-for动态增减),去掉adsFetched标志位即可实现配置更新后自动重新发起请求 - Nuxt3场景下逻辑完全一致,仅需把Vuex替换为Pinia,页面fetch替换为
useFetch即可
内容的提问来源于stack exchange,提问作者zcserei
相关产品推荐
相关产品推荐

