Axios快速上手

该文章已生成可运行项目,

目录

1 Axios简介

2 Axios安装

3 Axios简单使用

4 Axios进阶使用

4.1 全局统一配置

4.2 导出axios实例

4.3 拦截器

4.3.1 请求拦截器

4.3.2 响应拦截器

5 Axios项目使用

5.1 跨域问题

5.1.1 同源策略与跨域问题

5.1.2 跨域问题解决方案

5.2 代理服务器

5.2.1 三种常见场景的跨域问题

5.2.2 代理服务器配置

5.3 封装使用流程

5.3.1 axios实例封装

5.3.2 代理服务器封装

5.3.3 请求接口方法封装


1 Axios简介

        Axios是一个基于promise( Promise是JavaScript的异步编程的对象,用来接收异步操作成功或失败以及数据的对象)的网络请求库,可用于node.js和浏览器中。用于node.js就是后端开发发送http请求,用于浏览器就是前端开发发送ajax请求。

        Aaxios(ajax i/o system)本质上也是对原生XHR(XMLHttpReques)的封装,只不过它是基于promise的,是promise的实现版本,符合最新的ES规范。

        Axios作为请求库,具有如下优势:

  • 标准化:统一浏览器/Node环境请求接口。
  • 拦截器机制:可拦截请求/响应,实现全局逻辑(如Token注入、错误处理)。
  • 自动转换:请求/响应数据自动转为JSON,支持自定义转换逻辑。
  • 取消请求:通过CancelToken中止长时间未响应的请求。

2 Axios安装

        终端打开项目地址,输入如下命令:

npm install axios  # Node 环境

3 Axios简单使用

        要使用Axios,首先需要引入axios包,然后通过create()创建axios实例,才能使用:

import axios from 'axios'
// GET 请求(参数自动拼接到 URL)
axios.get('/user',  { params: { id: 123 } })
  .then(res => console.log(res.data)) 
  .catch(err => console.error(err)); 
 
// POST 请求(自动序列化 JSON)
axios.post('/login',  { username: 'admin', pwd: '123' })
  .then(res => console.log(res)); 

        上述通过引入axios,使用get发送GET请求,使用post发送POST请求,通过Promise对象的.then和.catch等链式调用的方式来获取成功态的Promise实例和拒绝态的Promise实例(失败)。

        除了get和post请求,还有其它请求方式:

  • get:获取数据
  • post:提交数据(表单提交与文件上传)
  • patch:更新数据(只将修改的数据推送到后端(服务端))
  • put:更新数据(所有数据推送到服务端)
  • delete:删除数据

4 Axios进阶使用

        上述使用方式特点是功能简单,并且只能在单个组件中使用,如果要全局使用,就可以创建Axios实例并导出,灵活配置后端URL:

4.1 全局统一配置

        全局统一配置Axios实例一般需要单独创建js文件,在其中创建Axios实例并导出:

// 创建 axios 实例
const instance = axios.create({
  //后端服务器ip地址
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 600000
})

        baseURL参数是后端服务器的ip地址,timeout是超时时间。

        建议:后端服务器ip地址不要写死,根据环境变量或常量进行灵活动态变化。

4.2 导出axios实例

        通过export导出默认的axios实例,接收5个参数:

// 导出自定义请求函数(url是接口地址(因为基本ip地址已经封装,只需接口地址再拼接即可)、请求类型、数据、参数、请求头)
export default ({ url, method, data, params, header }) => {
  return instance({
    url,
    method,
    data,
    params,
    header
  })
}

        要使用axios实例的组件需要导入该实例,并传入url(接口地址)、method(请求方法)、data(发送的数据)、params(请求参数)、header(请求头),即可发送请求。

        接口地址会被自动拼接到后端服务器ip后从而发送完整的请求路径。

4.3 拦截器

        可以在创建axios实例后,对实例添加拦截器,然后在请求发送前和响应接收前做一些特殊处理(公共处理:每个接口都需要进行步骤,比如用户鉴权Token)。

4.3.1 请求拦截器

        请求拦截器在请求发送前进行拦截请求,并处理一些事情,比如请求头添加Token:

// 添加请求拦截器
instance.interceptors.request.use(
  (config) => {
    // config就是和此次请求相关的信息,包含请求地址,方法,参数,头等
    const userStore = useUserStore()
    const { token } = userStore
    // 如果有Token,说明已经登录过,所有的登录后请求头应该添加Token
    if (token) {
      config.headers.Authorization = token
    }
    // 必须返回config,否则无法获取响应数据
    return config
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)

4.3.2 响应拦截器

        响应拦截器是在响应被处理前进行拦截,可以对响应数据进行状态码验证、数据解构等操作:

// 添加响应拦截器
instance.interceptors.response.use(
  (response) => {
    // 解构:从响应response对象的data属性才能拿到后端返回的数据
    const { code, data, msg } = response.data
    if (code !== 200000) {
      // 返回一个失败态的 Promise 实例
      // 拦截器后的接口请求方就会收到错误的Promise实例,即被.catch到
      return Promise.reject(new Error(msg))
    }
    // 否则返回纯粹的 data 数据
    return data
  },
  (error) => {
    // 所有的接口响应失败都必须先执行这里
    const { response, status } = error
    //比如http状态是401
    if (status === 401) {
        // token 过期
        // TODO相应的一些关于token删除的操作
        // 返回拒绝态的Promise实例
        return Promise.reject(new Error('token过期'))
    } else {
      // 其它失败状态
      const { code, msg } = response.data
      // 返回失败态的Promise实例,并携带错误信息
      return Promise.reject({
        code,
        msg
      })
    }
  }
)

5 Axios项目使用

        前端在开发过程中,如果直接使用axios发送请求,大概率出现跨域问题,要了解跨域问题和解决方案,首先就需要了解同源策略:

5.1 跨域问题

5.1.1 同源策略与跨域问题

        (1)同源策略

        首先声明同源策略是浏览器的行为策略

        同源策略:同源是指浏览器发出的请求所访问的服务器的url协议一样、域名一样、端口号一样,三者都一样则称为同源。

        (2)跨域问题

        跨域问题:同源的三个条件只要有一个不一样就是跨域,这是浏览器禁止的行为,浏览器出于安全考虑,采用同源策略,不允许跨域请求。

        理解跨域问题的核心是理解浏览器发送请求的行为流程:这里的浏览器的同源策略是对前端JS代码的约束浏览器通过地址栏输入URL访问前端静态资源是允许的。而浏览器获取从前端服务器获取到的静态资源中,JS部分访问后端服务器(不同源,和浏览器访问前端资源的URL至少端口号或域名不一样),因此才会发生跨域问题。

        比如:浏览器请求前端服务器路径http://localhost:5173,前端服务器的js代码请求后端服务器路径http://localhost:8080,两者端口号不同,因此不满足同源策略。当然这种情况是前端服务器和后端服务器都部署在一台主机上,使用端口号不同。

5.1.2 跨域问题解决方案

        (1)CORS:后端开启跨域资源共享,前端不需要做什么事。

        (2)请求代理:浏览器访问本地服务器(这也不涉及跨域,因为这是浏览器地址栏URL的基础导航功能,并且自己访问自己凭什么不可以),由本地服务器访问后端服务器,服务器之间不存在跨域问题(因为请求链不涉及浏览器)。

5.2 代理服务器

5.2.1 三种常见场景的跨域问题

        传统前后端还未完全分离的项目中,静态资源存储在后端服务器中,浏览器从后端服务器获取静态资源,静态资源中JS代码部分请求后端服务器,因此浏览器请求的URL和后端服务器URL是同源的(同协议、同域名、同端口),只是数据接口的路由地址不同,因此不存在跨域问题。

        前后端分离项目,如果未配置跨域请求代理,前端静态资源部署在前端服务器中(Node服务器),浏览器请求前端静态资源,请求的URL是前端服务器的URL,而静态资源的JS部分请求的是后端服务器URL,如果前端服务器和后端服务器在同一个主机上,由于至少端口号不同,因此不同源,即发生跨域问题;如果前端服务器和后端服务器不在同一台主机上,那至少域名不相同(ip),因此也会发生跨域问题。

        如果配置跨域请求代理,代理服务器也是前端服务器(仅需添加配置项),因此浏览器请求前端服务器获取静态资源,JS部分请求跨域请求代理,由跨域请求代理转发请求(服务器之间访问不存在浏览器同源策略的限制),此时就不会发生跨域问题。

5.2.2 代理服务器配置

export default defineConfig({
  // 开发服务器配置
  server: {
    port: 80, // 端口
    open: true, // 自动打开浏览器
    // 配置跨域请求代理
    proxy: {
      '/dev-api': {
        // 目前服务器地址(目前开发阶段暂时用本地ip+端口号模拟,实际应该用后端服务器的ip地址+端口号)
        target: 'http://127.0.0.1:18081',
        changeOrigin: true, // 改变请求头的origin源,保证到达后端服务器的值是target值而不是前端请求路径
        // 路径重写:不进行重写,请求到达后端就是:服务器地址+/dev-api+请求的接口地址
        // 如果后端服务器的接口地址没有/dev-api,就会请求不到资源,因此需要替换为空字符串
        rewrite: (path) => path.replace(/^\/dev-api/, '')
      }
    }
  }
})

        在vite.config.js中配置Node服务器server,port是前端服务器的端口,open是启动项目自动打开首页策略。

        proxy是跨域请求代理的配置项,配置转发路由为/dev-api,target是后端服务器地址,changeOrigin为true表示改变请求头的origin源,确保后端接收的请求的目标URL是后端服务器的值而不是前端发出的值。rewrite表示对路径进行重写,去除/dev-api路由。

        即完整的流程如下:

        (1)前端服务器位于http://localhost:80,浏览器请求静态资源的URL为http:localhost:80/example/api(前端服务器地址+JS请求后端的接口路由)。

        (2)JS部分的Axios在请求路径添加http:localhost:80/dev-api/example/api发送到代理服务器(Node服务器监听80端口,如果请求路径是/dev-api,则由代理服务器处理该URL)。

        (3)后端服务器位于http://localhost:18081,代理服务器重写请求URL为http://localhost:18081/example/api并转发该请求,因此解决跨域请求问题。

5.3 封装使用流程

        由于Axios的使用流程比较固定,且每个前端涉及到请求后端的项目中都需要上述配置,因此可以对这部分进行封装,所有的项目都可以按照统一流程处理和使用:

5.3.1 axios实例封装

        创建js文件,配置如下内容:

        (1)导入Axios并创建实例:即全局统一配置部分;

        (2)配置实例的拦截器;

        (3)导出Axios实例。

5.3.2 代理服务器封装

        即5.2.2代理服务器配置部分,在vite.config.js文件添加。

5.3.3 请求接口方法封装

        创建api包,内部放js文件,文件内容是发送请求的方法。比如登录请求:

export const loginApi = ({ phone, password }) => {
  return request({
    method: 'post',
    url: '/admin/sys_user/login/password',
    data: {
      phone,
      password
    }
  })
}

        使用该方法就在对应的组件中导入该方法,传入参数即可发送请求。

本文章已经生成可运行项目
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值