axios详解及使用

axios是什么

​前端最流行的ajax请求库,react/vue官方都推荐使用axios发送ajax请求,是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。文档:https://hithub.com/axios/axios

细节:axios包括TypeScript定义。

特性

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应拦截
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

http相关

前后台交互的基本过程

  • 1.前台应用从浏览器端向服务器发送http请求(请求报文)
  • 2.后台服务器接收到请求后,调度服务器应用处理请求,向浏览器端返回Http响应(响应报文)
  • 3.浏览器端接收到响应,解析显示响应体/调用监事回调

HTTP请求报文

  • 1.请求行:请求方式/url
  • 2.多个请求头:一个请求头由name:value组成,如Host/Cookie/Content-type头
  • 3.请求体(有JSON格式和urlencoded)

HTTP响应报文

  • 1.响应行:响应状态吗/对应的文本(status/statusText)
  • 2.多个响应头:如Content-type、set-Cookie头
  • 3.响应体(响应体的内容只能是字符串或者Buffer形式)

不同类型的请求及作用

  • 1.Get请求:从服务端请求数据
  • 2.POst请求:向服务端添加数据
  • 3.Put请求:向服务端更新数据
  • 4.Delete:删除服务端数据

API分类

  • 1.Rest Api:
    • 发送请求进行CRUD那个操作由请求方式决定
    • 同一个请求路径可以进行多个操作(get/post/put/delete)
  • 2.非Rest Api:
    • 请求方式不决定请求的CRUD操作
    • 一个请求路径只对应一个操作,一般只有get/post

常见响应状态吗

  • 100–Continue 继续。客户端应继续请求
  • 200–OK,请求成功
  • 201–Created 已创建。成功请求并创建了新的资源
  • 202–已接受。已经接受请求,但并未处理完成
  • 204–No Content 无内容。服务器成功处理,但并未返回内容
  • 206–部分内容。服务器成功处理了部分Get请求
  • 301–永久移动。请求的资源已被永久移动到新的URL,返回信息会包括新的URL,浏览器会自动定向到新URL,今后任何新的请求都应使用新的URL代替
  • 302–临时移动。与301类似,但资源只是临时移动,客户端应继续使用原有的URL
  • 304–未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源,客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
  • 305–使用代理。所请求的资源必须通过使用代理访问。
  • 400–客户端请求的语法错误,服务器无法理解
  • 401–请求要求用户的身份认证
  • 403–服务器理解请求客户端的请求,但是拒绝执行此请求
  • 404–服务器无法根据客户端的请求找到资源,通过此状态码设计人员可以设置无法找到资源的个性页面
  • 405–客户端中的请求方法被禁止
  • 408–服务器等待客户端发送的请求时间过长,超时
  • 414–请求的URL过长,服务器无法处理
  • 500–服务器内部错误,无法完成请求
  • 505–服务器不支持请求的HTTP协议的版本,无法完成处理

HTTP常用的请求头

  • Accept–可接受的响应内容类型(Content-types)
  • Accept-Charset–可接受的字符集
  • Accept-Encoding–可接受的响应内容的编码方式
  • Authorization–用于表示HTTP协议中需要认证资源的认证信息
  • Cookie–之前服务器通过set-Cookie设置的一个HTTP协议Cookie

HTTP强缓存和协商缓存

对于客户端来说,HTTP缓存是web性能优化的重要手段。

优势

  • 减少了冗余的数据传递,节省宽带流量
  • 减少了服务器的负担,大大提高了网站性能
  • 加快了客户端加载网页的速度 这也正是HTTP缓存属于客户端缓存的原因。
  • 用户体验好

缺点:

  • 缓存中的数据可能与服务器的数据不一致
  • 消耗内存

浏览器缓存一般是针对静态资源(js/css/img等),我们将缓存分为强缓存和协商缓存,两者的主要区别是使用本地缓存的时候,是否需要向服务器验证本地缓存是否依旧有效。顾名思义,协商缓存,就是需要和服务器进行协商,最终确定是否使用本地缓存。

缓存相关 header
  • Expires:响应头,代表该资源的过期时间。
  • Cache-Control:请求/响应头,缓存控制字段,精确控制缓存策略。
  • If-Modified-Since:请求头,资源最近修改时间,由浏览器告诉服务器。
  • Last-Modified:响应头,资源最近修改时间,由服务器告诉浏览器,和If-Modified-Since成对出现,。
  • Etag:响应头,资源标识,由服务器告诉浏览器。
  • If-None-Match:请求头,缓存资源标识,由浏览器告诉服务器,和Etag成对出现。
强缓存

强制缓存整体流程比较简单,就是在第一次访问服务器取到数据之后,在过期时间之内不会再去重复请求。实现这个流程的核心就是如何知道当前时间是否超过了过期时间。

强制缓存的过期时间通过第一次访问服务器时返回的响应头获取。在 http 1.0 和 http 1.1 版本中通过不同的响应头字段实现。

http 1.0强缓存

在http1.0中,强缓存是通过expires响应头实现的,表示资源未来会过期的时间。该值是一个GMT时间格式个字符串,发起请求时间过了 expires设定的时间,表示资源缓存到期,会发送请求给服务器重新请求资源。如果发起请求时间没超过那么浏览器会直接读取本地缓存数据库中的信息(from memory cache or from disk cache)两种方式根据浏览器的策略随机获取。

from memory cache:字面理解是从内存中,其实也是字面的含义,这个资源是直接从内存中拿到的,不会请求服务器一般已经加载过该资源且缓存在了内存当中,当关闭该页面时,此资源就被内存释放掉了,再次重新打开相同页面时不会出现from memory cache的情况

from disk cache:同上类似,此资源是从磁盘当中取出的,也是在已经在之前的某个时间加载过该资源,不会请求服务器但是此资源不会随着该页面的关闭而释放掉,因为是存在硬盘当中的,下次打开仍会from disk cache

http 1.1强缓存

在 http 1.1 版本中,强制缓存通过 Cache-Control 响应头来实现。Cache-Control 拥有多个值

private:客户端可以缓存,不允许被中间代理服务器缓存。
public:客户端和代理服务器均可缓存;
max-age=xxx:缓存的资源将在 xxx 秒后过期;
no-cache:浏览器不做缓存检查;每次访问资源,浏览器都要向服务器询问,如果文件没变化,服务器只告诉浏览器继续使用缓存(304),需要使用协商缓存来验证是否过期;
no-store:浏览器和中间代理服务器都不能缓存资源

最常用的字段就是 max-age=xxx ,表示缓存的资源将在 xxx 秒后过期。一般来说,为了兼容,两个版本的强制缓存都会被实现。http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。浏览器先检查 Cache-Control,如果有,则以 Cache-Control 为准,忽略 Expires。如果没有 Cache-Control,则以 Expires 为准。

协商缓存

协商缓存每次读取数据时都需要跟服务器通信,并且会增加缓存标识。在第一次请求服务器时,服务器会返回资源,并且返回一个资源的缓存标识,一起存到浏览器的缓存数据库。当第二次请求资源时,浏览器会首先将缓存标识发送给服务器,服务器拿到标识后判断标识是否匹配,如果不匹配,表示资源有更新,服务器会将新数据和新的缓存标识一起返回到浏览器;如果缓存标识匹配,表示资源没有更新,并且返回 304 状态码,浏览器就读取本地缓存服务器中的数据。

在 http 1.0 和 http 1.1 版本中也是不同的实现

http 1.0协商缓存

在 http 1.0 版本中,第一次请求资源时服务器通过 Last-Modified 来设置响应头的缓存标识,并且把资源最后修改的时间作为值填入,然后将资源返回给浏览器。在第二次请求时,浏览器会首先带上 If-Modified-Since 请求头去访问服务器,服务器会将 If-Modified-Since 中携带的时间与资源修改的时间匹配,如果时间不一致,服务器会返回新的资源,并且将 Last-Modified 值更新,作为响应头返回给浏览器。如果时间一致,表示资源没有更新,服务器返回 304 状态码,浏览器拿到响应状态码后从本地缓存数据库中读取缓存资源。

这种方式有一个弊端,就是当服务器中的资源增加了一个字符,后来又把这个字符删掉,本身资源文件并没有发生变化,但修改时间发生了变化。当下次请求过来时,服务器也会把这个本来没有变化的资源重新返回给浏览器。

http 1.1协商缓存

在 http 1.1 版本中,服务器通过 Etag 来设置响应头缓存标识。Etag 的值由服务端生成。在第一次请求时,服务器会将资源和 Etag 一并返回给浏览器,浏览器将两者缓存到本地缓存数据库。在第二次请求时,浏览器会将 Etag 信息放到 If-None-Match 请求头去访问服务器,服务器收到请求后,会将服务器中的文件标识与浏览器发来的标识进行对比,如果不相同,服务器返回更新的资源和新的 Etag ,如果相同,服务器返回 304 状态码,浏览器读取缓存。

同样的,一般来讲为了兼容,两个版本的协商缓存都会被实现,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。

etag主要解决了Last-Modified一些无法解决的问题

一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新get;

某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),if-modified-since能检查到的粒度是秒级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);

某些服务器不能精确的得到文件的最后修改时间。

nodejs设置

res.setHeader(‘Cache-Control’, ‘public, max-age=258900’);
res.setHeader(‘Last-Modified’, Mon, 24 Dec 2019 09:49:49 GMT);
res.setHeader(‘ETag’, ‘5c20abbd-e2e8’);

使用方案

了解了强缓存和协商缓存,会发现无论单独使用哪一种都无法满足我们的需要,建议:

  • 1.HTML采用协商缓存,用户每次请求index.html不拿浏览器缓存,直接请求服务器,这样就保证资源更新了,用户能马上访问到新资源,如果服务端返回304,这时候再拿浏览器的缓存的index.html。
  • 2.JS/CSS/IMG采用强缓存,打包的时候给文件名加上hash值

什么时候使用强缓存或者协商缓存呢?

  • 在第一次请求时,服务器会将页面最后修改时间通过Last-Modified标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个Etag,并发送给客户端.
  • 浏览器请求某一资源时,会先获取该资源缓存的header信息,然后根据header中的Cache-Control和Expires来判断是否过期。若没过期则直接从缓存中获取资源信息,包括缓存的header的信息,所以此次请求不会与服务器进行通信。这里判断是否过期,则是强缓存相关。
  • 如果显示已过期,浏览器会向服务器端发送请求,这个请求会携带第一次请求返回的有关缓存的header字段信息,比如客户端会通过If-None-Match头将先前服务器端发送过来的Etag发送给服务器,服务会对比这个客户端发过来的Etag是否与服务器的相同,若相同,就将If-None-Match的值设为false,返回状态304,客户端继续使用本地缓存,不解析服务器端发回来的数据,若不相同就将If-None-Match的值设为true,返回状态为200,客户端重新机械服务器端返回的数据;客户端还会通过If-Modified-Since头将先前服务器端发过来的最后修改时间戳发送给服务器,服务器端通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回最新的内容,如果是最新的,则返回304,客户端继续使用本地缓存。

get和post的区别

  • 1.get参数通过url传递,post放在request body中
  • 2.get请求在url中传递的参数是有长度限制的,而Post没有
  • 3.get比post更不安全,因为参数直接暴露在Url中,所以不能用来传递敏感信息
  • 4.get请求只能进行URL编码,而post支持多重编码方式
  • 5.get请求的参数会被完整保留在浏览历史记录里,而post中参数不会被保留
  • 6.GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。

json-server的使用

json-server是什么?

用来快速搭建REST API 的工具包

使用json-server
  • 1.在线文档:https://github.com/typicode/json-server
  • 2.下载:npm install -g json-server
  • 3.目标根目录下创建数据库json文件:dn.json
{
	"posts": [
		{ "id": 1, "title": "json-server", "author": "typicode" },
		{ "id": 2, "title": "json-server2", "author": "typicode" }
	],
	"comments": [
		{ "id": 1, "body": "some comment", "postId": 1 }
	],
	"profile": { "name": "typicode" }
}
  • 4.启动服务器执行命令:json-server --watch db.json

  • 5.使用浏览器访问测试
    http://localhost:3000/posts
    http://localhost:3000/posts/1

  • 使用axios访问测试

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div>
    <button onclick="testGet()">GET请求</button>
    <button onclick="testPost()">POST请求</button>
    <button onclick="testPut()">PUT请求</button>
    <button onclick="testDelete()">DELETE请求</button>
  </div>
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
  <script>
    function testGet(){
      axios.get('http://localhost:3000/posts').then(res=>{
        console.log(res)
      })
    }
    function testPost(){
      axios.post('http://localhost:3000/posts',{'title':'json-server3','author':'type'}).then(res=>{
        alert('ok')
      })
    }
    function testPut(){
      axios.put('http://localhost:3000/posts/2',{'title':'json'}).then(res=>{
        alert('ok')
      })
    }
    function testDelete(){
      axios.delete('http://127.0.0.1:3000/posts/2').then(res=>{
        alert('ok')
        })
    }
  </script>
</body>
</html>

XMLHttpRequest的基本使用

1.特点
  • 函数的返回值为promise,成功的结果为response,失败的结果为error
  • 能处理多种类型请求:get/post/put/delete
  • 函数的参数为一个配置对象:url/method/params/data
  • 响应json数据自动解析为js
2.区别ajax请求与一般的http请求

AJAX请求是一种特别的http请求:只有通过XHR/Fetch发送的是ajax请求,其他的一般是HTTP请求
浏览器端接收到响应

  • 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/跳转页面
  • ajax请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调函数并传入响应相关数据
3.使用xhr封装简版的axios
//get请求,从服务器获取数据
function axios({
  url,
  method='GET',
  params={},
  data={}
}){
  //返回一个promise对象
  return new Promise((resolve,reject)=>{
    //处理method小写转大写
    method =method.toUpperCase()

    //处理query参数(拼接到url上)id=1&xxx=abc
    let queryString=''
    Object.keys(params).forEach(key=>{
      queryString+=`${key}=${
        params[key]
      }&`
    })
    if(queryString){
      //去除最后的&
      queryString=queryString.substring(0,queryString.length-1)
      //拼接到url
      url+='?'+queryString
    }
    //执行异步AJAX请求
    //创建xhr对象
    const request = new XMLHttpRequest()
    //打开连接(初始化请求)
    request.open(method,url,true)
    //发送请求
    if(method==='GET'||method==='DELETE'){
      request.send()
    }else if(method==='PUT'||method==='POST'){
      //设置请求头,告诉服务器请求体的格式是json
      request.setRequestHeader('Content-Type','appliaction/json;charset=utf-8')
      //发送json格式的请求参数
      request.send(JSON.stringify(data))//异步执行
    }
    //绑定监听状态
    request.onreadystatechange=function(){
      //如果请求没有完成,直接结束
      if(request.readyState!==4){
        return;
      }
      // 如果响应状态码在[200, 300)之间代表成功,否则失败
      const {status,statusText}=request
      if(status>=200&&status<300){
        //准备结果数据对象response
        const response={
          data:JSON.parse(request.response),
          status,
          statusText
        }
        resolve(response)
      }else{
        reject(new Error('request error status is'+status))
      }
    }
  })
}

axios的理解和使用

1.axios是什么?
  • 前端最流行的ajax请求库,react/vue官方都推荐使用axios发送ajax请求
  • 文档:https://hithub.com/axios/axios
2.特点:
  • 基于xhr+promise的异步ajax请求库
  • 浏览器/node端都可以使用
  • 支持请求/响应拦截器
  • 支持请求取消
  • 请求/响应数据切换
  • 批量发送多个请求
3.axios常用语法:
  • axios(config)-通用/最本质的发送任意类型的请求方式,config请求对象,可以包含请求方式/请求路径/请求参数
  • axios.get(url,params)–get请求
  • axios.post(url,data)–向服务器添加数据
  • axios.put(url,data)–修改服务器中的数据
  • axios.delete(url,params)–删除服务器中的数据
  • axios.interceptors.request.use(config=>return config)//请求拦截器,一定要把请求对象config返回,可以在里面设置config的相关配置比如请求头的信息
  • axios.interceptors.response.use(res=>return res.data)//响应拦截器,可以对服务中的返回的数据做一定的处理返回
  • axios.create({})–创建一个axios实例,使用方法和axios一样,但是这个实例没有取消请求和执行多个异步请求的功能/没有axios.cancel()/axios.all(promise)/axios.spread()功能//它的里面可以接受一个对象,是axios的默认配置,包括baseURL,Timeout
  • axios.defaults.xxx–请求的默认全局配置(baseURl/method/timeout)
  • axios.cancel()–用于创建取消请求的错误对象
  • axios.CancelToken()–用于创建取消请求的token对象
  • axios.isCancel()–是否是一个取现请求的错误
  • axios.all(promise)–用于批量执行多个异步任务
4.拦截器函数/ajax请求/请求的回调函数的执行顺序
  • 说明:调用axios()并不是立即发送ajax请求,而是需要经过一个较长的流程
  • 流程:请求拦截器2=>请求拦截器1=>发送ajax请求=>响应拦截器1=>响应拦截器2=>得到响应回调
5.取消请求

基本流程:let cancel;(用于保存取消请求的函数)
配置cancelToken对象:cancelToken:new axios.CancalToken(c=>cancel=c)
在后面特定时机调用cancel函数取消请求
在错误回调中判断如果error是cancel,做相应处理

常见的配置选项

请求配置

{
   // `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 && 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` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

   // `config` 是为请求提供的配置信息
  config: {},

  request: {}
}

axios的简易xhr版本封装

function lyAxios({
  method = 'GET',
  url,
  params = {},
  data = {}
}) {
  return new Promise((resolve, reject) => {

    // 处理method方法转为大写
    method = method.toUpperCase()

    //处理query参数拼接到url上
    let queryString = ''
    Object.keys(params).forEach(key => {
      queryString += `${key}=${params[key]}&`
    })
    if (queryString) {
      // 去除最后的&
      queryString = queryString.substring(0, queryString.length - 1)
      // 拼接到url
      url += '?' + queryString
    }

    // 创建ajax请求方式
    // 1.创建xhr对象
    const xhr = new XMLHttpRequest()

    // 2.设置请求的方式及参数
    xhr.open(method, url, true)

    // 3.发送请求
    if (method === 'GET' || method === 'DELETE') {
      xhr.send()
    } else if (method === 'POST' || method === 'PUT') {
      // 设置请求头,告诉服务器发送的数据的格式
      xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8')
      xhr.send(JSON.stringify(data))
    }

    // 4.判断请求的状态
    xhr.onreadystatechange = function () {
      //如果请求没有完成,直接结束
      if (xhr.readyState !== 4) {
        return;
      }
      const {status,statusText}=xhr
      if (status >= 200 && status < 300) {

        // 5.接受响应信息
        //准备结果数据对象response
        const response = {
          data: JSON.parse(xhr.response),
        }
        return resolve(response)
      } else {
        reject(new Error('request error is' + xhr.status))
      }
    }

  })
}

axios的默认发送数据格式

默认情况下,axios将JavaScript对象序列化为JSON。 要以application / x-www-form-urlencoded格式发送数据,您可以使用以下选项之一。

浏览器

在浏览器中,您可以使用URLSearchParams API,如下所示:

const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);

请注意,所有浏览器都不支持URLSearchParams(请参阅caniuse.com),但可以使用polyfill(确保填充全局环境)。

或者,您可以使用qs库编码数据:

const qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 }));

或者以另一种方式(ES6),

import qs from 'qs';
const data = { 'bar': 123 };
const options = {
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  data: qs.stringify(data),
  url,
};
axios(options);

Node.js
在node.js中,您可以使用querystring模块,如下所示:

const querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值