取消nuxt fetch hook的请求

Dep*_*pka 5 javascript vue.js axios vuex nuxt.js

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

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

路由器.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()
  })
}
Run Code Online (Sandbox Code Playgroud)

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)
  })
}
Run Code Online (Sandbox Code Playgroud)

以及一个用于取消令牌的小型 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')
  }
}
Run Code Online (Sandbox Code Playgroud)

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

这里的 fetch 钩子示例:

async fetch () {
  await this.$store.dispatch('runs/getRunsOverview')
}
Run Code Online (Sandbox Code Playgroud)

调度操作的示例:

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

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

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

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

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--)
}
Run Code Online (Sandbox Code Playgroud)

也尝试过按照 @kissu 在评论中建议的方式使用 async/await 来完成所有操作,但没有成功:/