Ajax和Axios实现

打印 上一主题 下一主题

主题 775|帖子 775|积分 2325

实现原生Ajax

简介

AJAX = 异步 JavaScript 和 XML。
AJAX 是一种用于创建快速动态网页的技能。
通过在后台与服务器进行少量数据互换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的环境下,对网页的某部门进行更新。
详细先容请移步AJAX 简介 | 菜鸟教程
最简版本

  1. function myAjax(method, url) {
  2.   const xhr = new XMLHttpRequest()
  3.   xhr.open(method, url)
  4.   xhr.onreadystatechange = function () {
  5.     if (xhr.readyState === 4) {
  6.       if (xhr.status === 200 || xhr.status === 304) {
  7.         console.log(xhr.responseText);
  8.       } else {
  9.         console.log(new Error(xhr.statusText));
  10.       }
  11.     }
  12.   }
  13.   xhr.send()
  14. }
复制代码
带promis版本

  1. function myAjax(method, url) {
  2.   return new Promise((resolve, reject) => {
  3.     const xhr = new XMLHttpRequest()
  4.     xhr.open(method, url)
  5.     xhr.onreadystatechange = function () {
  6.       if (xhr.readyState === 4) {
  7.         if (xhr.status === 200 || xhr.status === 304) {
  8.           resolve(xhr.responseText)
  9.         } else {
  10.           resolve(new Error(xhr.statusText))
  11.         }
  12.       }
  13.     }
  14.     xhr.send()
  15.   })
  16. }
复制代码
实现Axios

在平时写项目中大部门都会用到axios,但是对axios的实现却没怎么相识过,本日趁着休息,用js实现axios
简介

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它利用原生 node.js http 模块, 而在客户端 (浏览端) 则利用 XMLHttpRequests。
详细详细先容请移步起步 | Axios中文文档 | Axios中文网
这里实现出几个主要的方法,包罗post请求方法,create配置方法,以及拦截器的方法。
1.post方法

实现前先写一个类,在类的原型对象上进行方法的实现
  1. function cAxios() {
  2. }
复制代码
实现时注意两点:


  • axios的post的方法返回的是一个promise对象
  • axios的post的方法的data参数是一个对象,而原生的XMLHttpRequest对象的send方法参数是string
所以需要在send方法里面把data参数转化为JSON格式的字符串
  1. cAxios.prototype.post = function (method, url, data) {
  2.   return new Promise((resolve, reject) => {
  3.     const xhr = new XMLHttpRequest()
  4.     xhr.open(method, url)
  5.     xhr.onreadystatechange = function () {
  6.       if (xhr.readyState === 4) {
  7.         if (xhr.status === 200 || xhr.status === 304) {
  8.           resolve(xhr.responseText)
  9.         } else {
  10.           reject(new Error(reject.statusText))
  11.         }
  12.       }
  13.     }
  14.     xhr.send(JSON.stringify(data))
  15.   })
  16. }
复制代码
get方法也是一样的,不再形貌
2.create方法

axios.create(config)

  • 根据指定配置创建一个新的 axios, 也就就每个新 axios 都有自己的配置(主要是请求头的配置)
  • 新 axios 只是没有取消请求和批量发请求的方法, 其它所有语法都是同等的
这里的实现只是列举了headers和baseUrl这两个属性
  1. cAxios.prototype.create = function (obj) {
  2.   let axios = new cAxios()
  3.   axios.headers = obj.headers;
  4.   axios.baseUrl = obj.baseUrl;
  5.   return axios
  6. }
复制代码
所以假如我们设置请求头以后,调用post方法需要带上这些参数,因此post方法需要修改
起首需要写一个方法来配置请求头
  1. function setHeaders(xhr, headers){
  2.   for(let key in headers) {
  3.     xhr.setquestHeader(key, headers[key])
  4.   }
  5. }
复制代码
在post方法中,在ajax发送请求之前调用即可
  1. setHeaders(xhr, this.headers)
复制代码
3.拦截器

axios的拦截器分为请求拦截器和响应拦截器
寄义:在请求或响应被 then 或 catch 处理前拦截它们。
官网实例
  1. // 添加请求拦截器
  2. axios.interceptors.request.use(function (config) {
  3.     // 在发送请求之前做些什么
  4.     return config;
  5.   }, function (error) {
  6.     // 对请求错误做些什么
  7.     return Promise.reject(error);
  8.   });
  9. // 添加响应拦截器
  10. axios.interceptors.response.use(function (response) {
  11.     // 2xx 范围内的状态码都会触发该函数。
  12.     // 对响应数据做点什么
  13.     return response;
  14.   }, function (error) {
  15.     // 超出 2xx 范围的状态码都会触发该函数。
  16.     // 对响应错误做点什么
  17.     return Promise.reject(error);
  18.   });
复制代码
这里可以看到interceptors是一个对象,里面包含request和response属性
本文实现不考虑use
我们需要在类里面实现一下interceptors
  1. this.interceptors = {
  2.    request(fn) {
  3.      _this.saveReqFn.push(fn)
  4.    },
  5.    response(fn) {
  6.      _this.saveResFn.push(fn)
  7.    }
  8. }
复制代码
假如我们想在外边调用请求拦截器或者响应拦截器,需要传递一个回调函数作为拦截器的参数
所以在我们这里我们需要把这个回调函数生存下来(考虑到有多个拦截器,所以我们接纳数组生存)。
同时我们也要写一个data用于存放请求时的数据(由于在请求拦截器的回调函数中,有一个config参数,它包含着请求的数据)
  1. function cAxios() {
  2.   // 保存请求拦截器中的回调函数
  3.   this.saveReqFn = []
  4.   // 保存响应拦截器中的回调函数
  5.   this.saveResFn = []
  6.   // 保存请求的数据
  7.   this.data = []
  8.   let _this = this
  9.   this.interceptors = {
  10.     request(fn) {
  11.       _this.saveReqFn.push(fn)
  12.     },
  13.     response(fn) {
  14.       _this.saveResFn.push(fn)
  15.     }
  16.   }
  17. }
复制代码
如何调用?
好比在post方法中,请求拦截器应该发送请求之前调用,响应拦截器在返回数据之前调用
  1. cAxios.prototype.post = function (method, url, data) {
  2.   // 保存请求的数据
  3.   this.data = data
  4.   let _this = this
  5.   // 在发送请求之前调用请求拦截器的回调函数
  6.   if (this.saveReqFn?.length) {
  7.     this.saveReqFn.forEach(fn => {
  8.       fn(this)
  9.     })
  10.   }
  11.   return new Promise((resolve, reject) => {
  12.     const xhr = new XMLHttpRequest()
  13.     xhr.open(method, url)
  14.     setHeaders(xhr, this.headers)
  15.     xhr.onreadystatechange = function () {
  16.       if (xhr.readyState === 4) {
  17.         if (xhr.status === 200 || xhr.status === 304) {
  18.           // 创建一个新的对象,将响应的数据保存到新的对象中
  19.           let newData = {}
  20.           newData.data = JSON.parse(xhr.responseText)
  21.           // 在返回数据之前调用响应拦截器的回调函数
  22.           if (_this.saveResFn?.length) {
  23.             _this.saveResFn.forEach(fn => {
  24.               fn(newData)
  25.             })
  26.           }
  27.           resolve(xhr.responseText)
  28.         } else {
  29.           reject(new Error(xhr.statusText))
  30.         }
  31.       }
  32.     }
  33.     xhr.send(JSON.stringify(data))
  34.   })
  35. }
复制代码
4.完整代码

  1. function cAxios() {
  2.   // 保存请求拦截器中的回调函数
  3.   this.saveReqFn = []
  4.   // 保存响应拦截器中的回调函数
  5.   this.saveResFn = []
  6.   // 保存请求的数据
  7.   this.data = []
  8.   let _this = this
  9.   this.interceptors = {
  10.     request(fn) {
  11.       _this.saveReqFn.push(fn)
  12.     },
  13.     response(fn) {
  14.       _this.saveResFn.push(fn)
  15.     }
  16.   }
  17. }function setHeaders(xhr, headers) {  for (let key in headers) {    xhr.setquestHeader(key, headers[key])  }}cAxios.prototype.create = function (obj) {
  18.   let axios = new cAxios()
  19.   axios.headers = obj.headers;
  20.   axios.baseUrl = obj.baseUrl;
  21.   return axios
  22. }cAxios.prototype.post = function (method, url, data) {  // 生存请求的数据  this.data = data  let _this = this  // 在发送请求之前调用请求拦截器的回调函数  if (this.saveReqFn?.length) {    this.saveReqFn.forEach(fn => {      fn(this)    })  }  return new Promise((resolve, reject) => {    const xhr = new XMLHttpRequest()    xhr.open(method, url)    setHeaders(xhr, this.headers)    xhr.onreadystatechange = function () {      if (xhr.readyState === 4) {        if (xhr.status === 200 || xhr.status === 304) {          // 创建一个新的对象,将请求的数据生存到新的对象中          let newData = {}          newData.data = JSON.parse(xhr.responseText)          // 在返回数据之前调用响应拦截器的回调函数          if (_this.saveResFn?.length) {            _this.saveResFn.forEach(fn => {              fn(newData)            })          }          resolve(xhr.responseText)        } else {          reject(new Error(xhr.statusText))        }      }    }    xhr.send(JSON.stringify(data))  })}let axios = new cAxios()export {  axios}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表