You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:45:03