取消nuxt fetch钩子的请求

时间:2021-06-15 09:21:41

标签: javascript vue.js axios nuxt.js vuex

由于 Nuxt 的 fetch hooks 不能并行运行,我需要一种方法来取消导航到其他路由时在 fetch hook 中完成的请求,这样用户在登陆导航到的主页时不必等待第一次 fetch 完成其他。所以我找到了这种方法:How to cancel all Axios requests on route change

所以我为 Next 创建了这些插件文件:

router.js

export default ({ app, store }) => {
  // Every time the route changes (fired on initialization too)
  app.router.beforeEach((to, from, next) => {
    store.dispatch('cancel/cancel_pending_requests')
    next()
  })
}

axios.js

export default function ({ $axios, redirect, store }) {
  $axios.onRequest((config) => {
    const source = $axios.CancelToken.source()

    config.cancelToken = source.token
    store.commit('cancel/ADD_CANCEL_TOKEN', source)
    return config
  }, function (error) {
    return Promise.reject(error)
  })
}

和一个用于取消令牌的小型 vuex 存储:

export const state = () => ({
  cancelTokens: []
})

export const mutations = {
  ADD_CANCEL_TOKEN (state, token) {
    state.cancelTokens.push(token)
  },
  CLEAR_CANCEL_TOKENS (state) {
    state.cancelTokens = []
  }
}

export const actions = {
  cancel_pending_requests ({ state, commit }) {
    state.cancelTokens.forEach((request, i) => {
      if (request.cancel) {
        request.cancel('Request canceled')
      }
    })
    commit('CLEAR_CANCEL_TOKENS')
  }
}

现在这种方法工作正常,我可以看到请求在路由更改时被 499 取消,但是,它在我的开发工具控制台中充斥着“获取错误()”错误。是否有一些首选/更好的方法来做到这一点?

此处获取钩子的示例:

async fetch () {
  await this.$store.dispatch('runs/getRunsOverview')
}

分派动作示例:

export const actions = {
  async getRunsOverview ({ commit }) {
    const data = await this.$axios.$get('api/frontend/runs')
    commit('SET_RUNS', data)
  }
}

编辑:我忘了提到我在这里使用 fetch 并将 fetchOnServer 设置为 False 来向用户显示一些加载占位符。

主要问题是充满错误的控制台,但我也可以看到它也进入了我的模板中的 $fetchState.error 分支,它在路由切换之前显示带有“出现问题”文本的 div。

编辑2: 仔细查看此错误的来源,它是 fetch.client.js 目录中的 mixin 文件 .nuxt/mixins。粘贴获取函数代码如下:

async function $_fetch() {
  this.$nuxt.nbFetching++
  this.$fetchState.pending = true
  this.$fetchState.error = null
  this._hydrated = false
  let error = null
  const startTime = Date.now()

  try {
    await this.$options.fetch.call(this)
  } catch (err) {
    if (process.dev) {
      console.error('Error in fetch():', err)
    }
    error = normalizeError(err)
  }

  const delayLeft = this._fetchDelay - (Date.now() - startTime)
  if (delayLeft > 0) {
    await new Promise(resolve => setTimeout(resolve, delayLeft))
  }

  this.$fetchState.error = error
  this.$fetchState.pending = false
  this.$fetchState.timestamp = Date.now()

  this.$nextTick(() => this.$nuxt.nbFetching--)
}

也尝试按照@kissu 在评论中的建议使用 async/await 进行所有操作,但没有运气:/

0 个答案:

没有答案