nuxt.js中使用axios以及二次封装

nuxtjs中使用axios 有两种方法:

1. 普通的方式:

1.1: npm或者yarn安装依赖包

npm install axios -S

普通使用方式网上查询,这里不再过多叙述。

2. 集成的方式:

2.1:首先安装 @nuxtjs/axios

npm install @nuxtjs/axios --save

备注: 当使用脚手架create nuxt-app创建项目时,会提示是否集成axios。

2.2:在项目根目录新建plugins/axios.js
javascript 复制代码
/**
 * 该插件中包含了axios的各种配置,以及axios二次封装
 * 注释掉了全局引入loading的方法,页面采用局部loading,若有需求可以放开。
 * 1.token管理
 * 2.响应和请求的错误处理
 * 3.请求的loding控制
 *
 * 使用时:$axios为nuxtjs集成的axios;$axios为"@nuxtjs/axios": "^5.13.6",
 * 作者:
 */

import _ from 'lodash'
import Vue from 'vue'
import { Loading, Message } from 'element-ui'
import { uuid } from '~/plugins/utils/uuid'

let loadingInstance = null

let needLoadingRequestCount = 0

let securityCheckLock = false

// 显示loading
function showLoading(target) {
  // 后面这个判断很重要,因为关闭时加了抖动,此时loading对象可能还存在,
  // 但needLoadingRequestCount已经变成0.避免这种情况下会重新创建个loading
  if (needLoadingRequestCount === 0 && !loadingInstance) {
    loadingInstance = Loading.service({
      lock: true,
      text: 'Loading',
      spinner: 'el-icon-loading',
      background: 'rgba(0, 0, 0, 0.7)',
    })
  }
  needLoadingRequestCount++
}

// 隐藏loading
function hideLoading() {
  needLoadingRequestCount--
  needLoadingRequestCount = Math.max(needLoadingRequestCount, 0) // 做个保护
  if (needLoadingRequestCount === 0) {
    // 关闭loading
    toHideLoading()
  }
}

// 防抖:将 300ms 间隔内的关闭 loading 便合并为一次。防止连续请求时, loading闪烁的问题。
const toHideLoading = _.debounce(() => {
  if (loadingInstance) {
    loadingInstance.close()
    loadingInstance = null
  }
}, 300)

// 如果想用redirect或者操作vuex的话需要对外暴露store和redirect
export default ({
  store,
  redirect,
  req,
  $axios,
  app,
  ...args
}) => {
  // 请求拦截器,后续的token管理配置在这里
  $axios.onRequest(
    (config) => {
      if (process.client) {
        // 浏览器执行的客户端代码
        if (config.headers.showLoading !== false) {
          // showLoading(config.headers.loadingTarget)
        }
      }
      if (process.server) {
        // node执行的服务端代码
        // node服务端做host穿透-重点在这里哟
        // config.headers.host = req.headers.host
        if (!config.url.includes(process.env.baseUrl)) {
          config.url = process.env.baseUrl + config.url
        }
      }

      const token = Vue.prototype.$sdk.getUser().authUser 
      if (token) {
        config.headers.authorization = 'Bearer ' + token
      }

      config.headers.traceId = uuid(32) // traceId,用于后端追踪日志

      return config
    },
    // 请求错误处理,暂时所有都提示
    (err) => {
      // 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
      if (err.config.headers.showLoading !== false) {
        hideLoading()
      }

      if (process.client) {
        Message.closeAll()
        Message.error({
          showClose: true,
          message: err,
        })
      }

      return Promise.reject(err)
    }
  )
  // 响应拦截器,处理header、config等数据,给应用层返回最简洁的数据data
  $axios.onResponse((res) => {
    const { data, headers } = res
    // 判断当前请求是否设置了不显示Loading
    if (headers?.showLoading !== false) {
      hideLoading()
    }
    if (data?.code === -1) {
      // 常规错误处理
      if (process.client) {
        Message.closeAll()
        Message.error({
          showClose: true,
          message: data.message,
        })
      }
    } else if (data?.type === 'application/json') {
      // 常规错误处理
      if (process.client) {
        Message.closeAll()
        Message.error({
          showClose: true,
          message: '文件不存在',
        })
      }
    } else if (data?.code === -555) {
      // token过期处理
      if (process.client) {
        Message.closeAll()
        Message.error({
          showClose: true,
          message: '登录过期,请重新登录!',
        })
        sessionStorage.clear()
      }
      redirect({
        path: '/login',
      }) //  跳转到登录页,或使用vuex提交数据
    } 

    if (data?.type === 'application/octet-stream') {
      return { data, headers }
    } else {
      return headers === undefined ? res : data
    }
  })
  // Error拦截器,出现错误的时候被调用
  $axios.onError((error) => {
    switch (error.response.status) {
      case 400:
        error.message = '请求错误'
        break

      case 401:
        error.message = '未授权,请登录'
        break

      case 403:
        error.message = '拒绝访问'
        break

      case 404:
        error.message = `请求地址出错: ${error.response.config.url}`
        break

      case 408:
        error.message = '请求超时'
        break

      case 500:
        error.message = '服务器内部错误'
        break

      case 501:
        error.message = '服务未实现'
        break

      case 502:
        error.message = '网关错误'
        break

      case 503:
        error.message = '服务不可用'
        break

      case 504:
        error.message = '网关超时'
        break

      case 505:
        error.message = 'HTTP版本不受支持'
        break
    }

    Message.error({
      showClose: true,
      message: error.message,
    })

    return Promise.resolve(false)
  })
}

2.3: nuxt.config.js中配置axios项

javascript 复制代码
    modules: [
        // https://go.nuxtjs.dev/axios
        '@nuxtjs/axios',
        
      ],

    axios: {
        proxy: true,
        prefix: '/api/',
        retry: { retries: 3 },
        common: {
          contentType: 'application/json',
        },
      },
2.4: store 中使用
javascript 复制代码
const baseUrl = '/base-service'

const state = () => ({

})

const mutations = {

}

const actions = {
  // 获取引擎列表
  async getList({ commit }, data) {
    return await this.$axios.post(
      `${baseUrl}/enginess/pageEnginesss`,
      data
    )
  },
  
}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
}
相关推荐
天平2 小时前
油猴脚本创建webworker踩坑记录
前端·javascript·typescript
山河木马8 小时前
渲染管线-计算得到gl_Position(顶点着色器)之后续GPU流程
javascript·webgl·图形学
竹林8189 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
kyriewen11 小时前
别再每次都 Google 了:我整理了前端日常最常踩的 10 个 Git 坑,附速查表
前端·javascript·git
SmartBoyW12 小时前
深入ECMAScript规范:彻底搞懂JS隐式类型转换与底层ToPrimitive机制
前端·javascript
用户8524950718413 小时前
解密 JavaScript 中的 this:谁才是真正的调用者?
javascript·面试
Heo13 小时前
Vite进阶用法详解
前端·javascript·面试
铁皮饭盒14 小时前
Next.js 风格路由内置?Bun FileSystemRouter 凭啥这么香
javascript
小林ixn15 小时前
别再背八股了!从 5 个真实场景彻底搞懂 JavaScript 的 this
javascript
东风破_16 小时前
JavaScript 面试常考的字符串算法:从反转字符串到回文判断
前端·javascript