前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

axios

作者头像
用户4793865
发布2023-01-12 16:37:20
4K0
发布2023-01-12 16:37:20
举报
文章被收录于专栏:前端小菜鸡yym前端小菜鸡yym

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

前端网络请求方式有哪些?

1 XHR

传统Ajax基于XMLHttpRequest 用的不多

2 JQuery ajax

我第一次接触ajax是从JQuery ajax开始的。但是对于现在的脚手架方式,不会有人往项目中引入jQuery。因为JQuery已经不太常用了。

3 fetch

基于Promise设计的,发送请求和获取数据进行了很好的分离。但也有缺点:它是一个较为底层的Api需要自己进行封装。

1️⃣ 比如需要自己配置Header的Content-Type等,不会默认携带cookie。这些都需要自己去封装。

2️⃣ 处理错误麻烦,只有网络错误才会reject(promise的api),Http状态码404、500不会被标记为reject

3️⃣ 不支持取消一个请求以及查看请求的进度。

axios

可以理解成 ajax i/o system。前端使用较多。 特点:在浏览器中发送XMLHttpRequests 请求、在node中发送http请求,支持Promise API 、拦截请求和响应、转换请求和响应数据

总而言之,在脚手架项目中也就是在fetch 和 axios二者中选择。

新建一个react项目

其实没有必要新建,这是我项目的地址:✈️

我的项目是React Hooks的项目,我们在pages/Home/index.tsx文件下新写一个请求。在这里我在useEffect()钩子中发起请求。如果你是React Class项目,可以在comoponentDidMount()声明周期中发起请求。

代码语言:javascript
复制
import React, { useEffect } from "react";
import axios from 'axios'
const Home:React.FC = () =>{
    
    useEffect(()=>{
        axios.get('api/users/test').then((res)=>console.log(res))
        // 再去修改数据
    },[])
    return(
       <>
       Home
       </>
    )
}
export default Home;

查看源码

index.d.ts

这个语法是TypeScript语法,但是并不是用TypeScript编写的。现在很多的库,在编写完之后写 d.ts文件。是TypeScript 定义文件。一些类型的定义文件。主要是为了我们跳转进去看到定义的类型。

AxiosInstance

按住Ctrl键 + 鼠标点击axios.get() 跳进去,可以发现它最主要让我们传入AxiosRequestConfig

image.png
image.png

AxiosRequestConfig

那么,我们再同样操作,看一下AxiosRequestConfig 究竟是什么。这是一个接口,

image.png
image.png

测试请求

刚才我们上面的请求中我请求的是我本地的node编写的后端,如需要可自行下载 🚁 当然,不是所有人都愿意去触摸后端,那么可以使用这个网站进行测试http://httpbin.org/#/

这里我们再说一下

正常来说,前端去调取非同源的后端,会产生跨域问题。解决跨域可以在前端处理,也可以再后端处理。在前端则需要安装http-proxy-middleware。当然真实项目中,最常用的是用Nginx进行反向代理。

言归正传,如下是我们发起的一个get请求

代码语言:javascript
复制
import React, { useEffect } from "react";
import axios from 'axios'
const Home:React.FC = () =>{
    
    useEffect(()=>{
       axios.get('http://httpbin.org/get').then((res)=>console.log(res))
    },[])
    return(
       <>
       Home
       </>
    )
}
export default Home;

这个get请求到的其实是一个html页面

image.png
image.png

get请求

写法一

在axios中传递一个对象参数。请求的url、参数、请求方式(GET PUT POST DELETE),默认的请求是GET请求,method其实可以不写。

axios返回的是一个Promise的对象,要想获得返回结果需要在 then 中获得,catch 处理异常。

代码语言:javascript
复制
import React, { useEffect } from 'react';
import axios from 'axios';
const Home: React.FC = () => {
  useEffect(() => {
    axios({
      url: 'http://httpbin.org/get',
      params: {
        name: 'sdss',
        age: 18,
      },
      method: 'GET',
    }).then(res => console.log(res))
      .catch(err=>{ console.error(err) });
  }, []);
  return <>Home</>;
};
export default Home;

如下:其实get方式传参,是在URL中传递的。 使用params进行传参,但是在post中就不能使用params了。

image.png
image.png

写法二

  • 参数1:URL
  • 参数2:请求传递参数
代码语言:javascript
复制
axios.get("http://httpbin.org/get",{
    params:{
        name:'test',
        age: 30
    }
}).then(res=>console.log(res)).catch(err=>console.error(err))

post请求

传递参数

这个传参我们就不能放到params中了 ,需要在data中传参数。

代码语言:javascript
复制
 axios({
        url:'http://httpbin.org/post',
        data:{
            name: 'koa',
            age: 40
        },
        method: 'POST'
    }).then(res=>{
        console.log(res)
    }).catch(err=>{
        console.error(err)
    })
  }, []);
image.png
image.png

写法二

代码语言:javascript
复制
axios.post("http://httpbin.org/post",{
        name:'lucky',
        age:20
    }).then(res=>console.log(res))

1.

无论是get请求还是post请求,实质上都是request请求。

代码语言:javascript
复制
axios.request({
    
})

我们跳到index.d.ts文件,但是这并不是axios功能实现的源码,只是一个描述文件,index.js才是功能代码。 我们可以看到index.js中也并没有写具体代码,而是因我那个了lib下的axios

image.png
image.png
image.png
image.png

我们看一下 axios.js文件 可以看到我们的axios是通过createInstance创建的实例,在创建实例中 绑定了原型上的request。所以本质上请求方式都是request。因此可以 axios()这么写也就是第一种写法。

image.png
image.png
image.png
image.png

2.

并没有 axios.get 那么为什么可以使用 axios.get那?我们选中Axios 然后 ctrl + 鼠标左键

image.png
image.png

跳入到了 core/Axios.js

  • 可以看到它遍历了 'delete', 'get', 'head', 'options',并把它们添加到了原型上,可以看到这四种方式是没有传入data参数的只有url和config,return后面调用的request函数中的data是config或者是空对象的data。
  • 下面的另一个方法 遍历了 'post', 'put', 'patch',这几中方式传入了url data 和 config,所以这几种请求是可以传data参数的。
image.png
image.png

处理返回值

Promise

同步代码去写异步操作

async await关键字的使用

我们用的是react hooks,正常来说,在useEffect的函数中写async关键字是可以的,

代码语言:javascript
复制
 useEffect( async() => { 
 
  const result = await axios({
        url: 'http://httpbin.org/post',
        data: {
          name: 'koa',
          age: 40,
        },
        method: 'POST',
      })
  },[])

但是,我还用到了TypeScript,所以会报错。那如果我们还是想要在useEffect中使用的话,我们就再定义一个函数,然后再useEffect中使用就好了

代码语言:javascript
复制
  const testAsync = async()=>{
       // async await
    const result = await axios({
        url: 'http://httpbin.org/post',
        data: {
          name: 'koa',
          age: 40,
        },
        method: 'POST',
      });
     console.log(result,'testAsync')
  }
 useEffect(() => {
     testAsync()
 },[])

同样也得到了我们想要的结果的。

image.png
image.png

获取错误信息

在使用Promise的then() API的时候,我们是可以再通过catch API 获得错误异常的。那么 async await这种写法怎么获得错误异常呢?

可以使用try..catch..

代码语言:javascript
复制
  const testAsync = async () => {
    try {
      // async await
      const result = await axios({
        url: 'http://httpbin.org/post',
        data: {
          name: 'koa',
          age: 40,
        },
        method: 'POST',
      });
      console.log(result, 'testAsync');
    } catch (error) {
        console.log(error)
    }
  };

API

合并多个请求:axios.all

axios.all 需要传入一个数组[],数组

async await的写法

代码语言:javascript
复制
 const testAsync1 = () => {
    try {
      // async await
      return axios({
        url: 'http://httpbin.org/post',
        data: {
          name: 'koa',
          age: 40,
        },
        method: 'POST',
      });
    //   console.log(result, 'testAsync');
    } catch (error) {
        console.log(error)
    }
  };
  const testAsync2 =() => {
    try {
      // async await
      return  axios({
        url: 'http://httpbin.org/get',
        params: {
          name: 'sdss',
          age: 18,
        },
        method: 'GET',
      })
    } catch (error) {
        console.log(error)
    }
  };
  // 注意 这里是 testAsync1()函数需要带() 因为其返回值不是Promise对象 
  const testAsync = async ()=>{
    const result = await axios.all([testAsync1(),testAsync2()])
    console.log(result)
  }

如图返回了一个数组,数组内分别是两个请求的结果对象

image.png
image.png

Promise的写法

不能在request1 request2后面写then,因为有then的出现就说明已经执行完毕了。也就是Promise的resolve结束了。返回结果也就会是[undefined,undefined]

代码语言:javascript
复制
useEffect(() => {
    // get请求
   const request1 = axios({
      url: 'http://httpbin.org/get',
      params: {
        name: 'sdss',
        age: 18,
      },
      method: 'GET',
    })

    // post请求
    const request2 =axios({
      url: 'http://httpbin.org/post',
      data: {
        name: 'koa',
        age: 40,
      },
      method: 'POST',
    })
    
    // 这里request1,request2返回的是Promise对象 所以不需要()
    axios.all([request1,request2]).then(res=>{
        console.log(res)
    }).catch(err=>{
        console.log(err)
    })
  }, []);

要想把两个接口的返回结果分开的话,我们可以使用数组的解构

代码语言:javascript
复制
 axios.all([request1,request2]).then(([res1,res2])=>{
        console.log(res1,res2)
    }).catch(err=>{
        console.log(err)
    })

看一下 源码其实axios.all本质上就是一个promise.all()

image.png
image.png

axios配置选项

请求配置

代码语言:javascript
复制
{
  // `url` 是用于请求的服务器 URL
 url: '/user',

 // `method` 是创建请求时使用的方法
 method: 'get', // default

 // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
 // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
 baseURL: 'https://some-domain.com/api/',

 // `transformRequest` 允许在向服务器发送前,修改请求数据
 // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
 // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
 transformRequest: [function (data, headers) {
   // 对 data 进行任意转换处理
   return data;
 }],

 // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
 transformResponse: [function (data) {
   // 对 data 进行任意转换处理
   return data;
 }],

 // `headers` 是即将被发送的自定义请求头
 headers: {'X-Requested-With': 'XMLHttpRequest'},

 // `params` 是即将与请求一起发送的 URL 参数
 // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
 params: {
   ID: 12345
 },

  // `paramsSerializer` 是一个负责 `params` 序列化的函数
 // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
 paramsSerializer: function(params) {
   return Qs.stringify(params, {arrayFormat: 'brackets'})
 },

 // `data` 是作为请求主体被发送的数据
 // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
 // 在没有设置 `transformRequest` 时,必须是以下类型之一:
 // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
 // - 浏览器专属:FormData, File, Blob
 // - Node 专属: Stream
 data: {
   firstName: 'Fred'
 },

 // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
 // 如果请求话费了超过 `timeout` 的时间,请求将被中断
 timeout: 1000,

  // `withCredentials` 表示跨域请求时是否需要使用凭证
 withCredentials: false, // default

 // `adapter` 允许自定义处理请求,以使测试更轻松
 // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
 adapter: function (config) {
   /* ... */
 },

// `auth` 表示应该使用 HTTP 基础验证,并提供凭据
 // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
 auth: {
   username: 'janedoe',
   password: 's00pers3cret'
 },

  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
 responseType: 'json', // default

 // `responseEncoding` indicates encoding to use for decoding responses
 // Note: Ignored for `responseType` of 'stream' or client-side requests
 responseEncoding: 'utf8', // default

  // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
 xsrfCookieName: 'XSRF-TOKEN', // default

 // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
 xsrfHeaderName: 'X-XSRF-TOKEN', // default

  // `onUploadProgress` 允许为上传处理进度事件
 onUploadProgress: function (progressEvent) {
   // Do whatever you want with the native progress event
 },

 // `onDownloadProgress` 允许为下载处理进度事件
 onDownloadProgress: function (progressEvent) {
   // 对原生进度事件的处理
 },

  // `maxContentLength` 定义允许的响应内容的最大尺寸
 maxContentLength: 2000,

 // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
 validateStatus: function (status) {
   return status >= 200 &amp;&amp; status < 300; // default
 },

 // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
 // 如果设置为0,将不会 follow 任何重定向
 maxRedirects: 5, // default

 // `socketPath` defines a UNIX Socket to be used in node.js.
 // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
 // Only either `socketPath` or `proxy` can be specified.
 // If both are specified, `socketPath` is used.
 socketPath: null, // default

 // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
 // `keepAlive` 默认没有启用
 httpAgent: new http.Agent({ keepAlive: true }),
 httpsAgent: new https.Agent({ keepAlive: true }),

 // 'proxy' 定义代理服务器的主机名称和端口
 // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
 // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
 proxy: {
   host: '127.0.0.1',
   port: 9000,
   auth: {
     username: 'mikeymike',
     password: 'rapunz3l'
   }
 },

 // `cancelToken` 指定用于取消请求的 cancel token
 // (查看后面的 Cancellation 这节了解更多)
 cancelToken: new CancelToken(function (cancel) {
 })
}

响应配置

  • 如图返回这个结构,并不是服务端(后端)返回我们的结构,只有data才是。
  • config是我们发送的配置信息。
  • header是这次响应的请求头。
  • request对应请求的request对象
image.png
image.png

配置默认值

全局的 axios 默认值

可以写到index.js

代码语言:javascript
复制
axios.defaults.baseURL = 'https://api.example.com'; 
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; 
// 如果只给post添加配置
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 

axios.create

再考虑一个问题,如果,去请求两台服务器 那么baseURL怎么办

可以创建多个实例 通过 axios.create

代码语言:javascript
复制
// 创建实例
const instance1 = axios.create({
  baseURL:'http://www.baidu.com',
  timeout:5000,
  headers:{

  }
})

const instance2 = axios.create({
  baseURL:'http://www.hao123.com',
  timeout:5000,
  headers:{
    
  }
})
// 使用
instance1 ({
    url: '/post'
})

instance2({
    url: '/get'
})

拦截器

请求拦截

代码语言:javascript
复制
axios.interceptors.request.use(config=>{
  // 1.发送请求时 在界面的中间位置显示loading的组件
  // 2.请求的用户必须携带token

  // 3.params/data做一些序列化的操作

  return config
},err=>{

})

响应拦截

代码语言:javascript
复制
axios.interceptors.response.use(res=>{
  return res.data
},err=>{
  if(err &amp;&amp; err.response){
    switch(err.responseInterceptor.status){
      case 400:
        console.log('请求错误')
        break;
      case 401:
        console.log('未授权')
        break;
      default:
        console.log('其他错误')
    }
  }
  return err
})

二次封装

进行封装,如果需要修改,只需要改一出即可。

在src新建service文件夹

当然这个名字随便取,只要你自己能看懂就行。

request.js

在文件夹下新建 request.js。这个文件对axios进行封装。通过axios.create创建一个instance实例(这里用到的一些配置变量我们又定义一个文件然后再引用),然后分别对instance进行请求拦截处理 和 响应拦截处理。

代码语言:javascript
复制
import axios from 'axios'
import { BASE_URL, TIMEOUT } from './config'
const instance = axios.create({
    baseURL: BASE_URL,
    timeout: TIMEOUT
})

instance.interceptors.request.use(config => {
    // 1.发送请求时 在界面的中间位置显示loading的组件
    
    // 2.请求的用户必须携带token

    // 3.params/data做一些序列化的操作

    return config
}, err => {

})
axios.interceptors.response.use(res => {
    return res.data
}, err => {
    if (err &amp;&amp; err.response) {
        switch (err.responseInterceptor.status) {
            case 400:
                console.log('请求错误')
                break;
            case 401:
                console.log('未授权')
                break;
            default:
                console.log('其他错误')
        }
    }
    return err
})

export default instance

config.js

定义一些配置变量,如baseUrl,timeout等。其中BASE_URL还对开发环境和正式环境进行了判断。

代码语言:javascript
复制
const devBaseURL = 'http://httpbin.org/'
const proBaseURL = 'http://production.org/'
// 进行修改
const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseURL : proBaseURL
const TIMEOUT = 5000
export { BASE_URL , TIMEOUT}

我们打印 process.env看一下

image.png
image.png

最后在页面调用

代码语言:javascript
复制
import React, { useEffect } from 'react';
// 根据不同层级引用
import request from '../../service/request'
const Home: React.FC = () => {
 
  useEffect(() => {
    // get请求
    request({
      url: '/get',
      params: {
        name: 'sdss',
        age: 18,
      },
      method: 'GET',
    }).then((res)=>console.log(res))
  }, []);
  return <>Home</>;
};
export default Home;
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-02-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前端网络请求方式有哪些?
    • 1 XHR
      • 2 JQuery ajax
        • 3 fetch
          • axios
          • 新建一个react项目
          • 查看源码
            • index.d.ts
              • AxiosInstance
              • AxiosRequestConfig
              • 测试请求
          • get请求
            • 写法一
              • 写法二
                • 传递参数
                  • 写法二
                  • 1.
                  • 2.
                  • 处理返回值
                    • Promise
                      • 同步代码去写异步操作
                        • async await关键字的使用
                        • 获取错误信息
                    • API
                      • 合并多个请求:axios.all
                        • async await的写法
                        • Promise的写法
                    • axios配置选项
                      • 请求配置
                        • 响应配置
                          • 配置默认值
                            • 全局的 axios 默认值
                            • axios.create
                            • 请求拦截
                            • 响应拦截
                            • 在src新建service文件夹
                            • request.js
                            • config.js
                            • 最后在页面调用
                        • 拦截器
                        • 二次封装
                        相关产品与服务
                        容器服务
                        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档