原生js 封装ajax请求超详细

Posted 流萤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生js 封装ajax请求超详细相关的知识,希望对你有一定的参考价值。

文章目录
XMLHttpRequest 对象
onreadystatechange 事件
setRequestHeader
处理响应
向服务器发送请求
思路说明
请求方式
完整代码

已经掌握AJAX基础的可以从思路说明开始看

XMLHttpRequest 对象

所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。

为了应对所有的现代浏览器:

  let xmlhttp;
  if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp = new XMLHttpRequest();
  } else {// code for IE6, IE5
       xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }

onreadystatechange 事件

每当 readyState 改变时,就会触发 onreadystatechange 事件。

readyState 属性存有 XMLHttpRequest 的状态信息。

属性描述
onreadystatechange存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。
readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。0: 请求未初始化1: 服务器连接已建立2: 请求已接收3: 请求处理中4: 请求已完成,且响应已就绪
status200: "OK"404: 未找到页面

当 readyState 等于 4 且状态为 200 时,表示响应已就绪:

xmlhttp.onreadystatechange = function () {
  if (xmlhttp.readyState == 4) {
      if (xmlhttp.status == 200) {
          var result = xmlhttp.responseText
          try{
              resolve(JSON.parse(result))
          }catch (e) {
              reject({errorMsg:\'数据格式错误\'})
          }
      } else {
         // console.log(\'error:xmlhttp.status =\', xmlhttp.status)
          reject(xmlhttp)
      }
  }
}

setRequestHeader

XMLHttpRequest.setRequestHeader() 是设置HTTP请求头部的方法。此方法必须在 open() 方法和 send() 之间调用。如果多次对同一个请求头赋值,只会生成一个合并了多个值的请求头。

如果没有设置 Accept 属性,则此发送出send() 的值为此属性的默认值/
语法:

xmlhttp.setRequestHeader(header, value);

处理响应

XMLHttpRequest() 对象的几种类型的响应属性

属性描述
responseText获得字符串形式的响应数据。
responseXML获得 XML 形式的响应数据。

解析和操作包含 html 文档的 responseText 属性

解析这些HTML标记主要有三种方式:

  1. 使用 XMLHttpRequest.responseXML 属性
  2. 将内容通过 fragment.body.innerHTML 注入到一个 文档片段 中,并遍历 DOM 中的片段
  3. 如果预先知道 HTML 文档的内容,可以使用 RegExp

不推荐第三种方式,因为如果 HTML 代码发生轻微变化,该方法将可能失败,一般直接用XMLHttpRequest.responseXML 属性

向服务器发送请求

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法

open():规定请求的类型、URL 以及是否异步处理请求。

open(method,url,async)

参数说明:

  • method:请求的类型;
  • GET 或 POST url:文件在服务器上的位置
  • async:true(异步)或 false(同步)

send() :将请求发送到服务器。

send(string)

参数说明:

  • string:仅用于 POST 请求

我的代码:

 xmlhttp.open(arg.method || \'GET\', arg.url, true);
 arg.headers = arg.headers || {};
  for (let key in arg.headers){
      xmlhttp.setRequestHeader(key, arg.headers[key]);
  }
  xmlhttp.send(arg.data);

思路说明

http请求有多种方式GET、POST、PUT...,先处理公共部分,封装一个createXMLHttp()方法

  1. 创建 XMLHttpRequest 对象
  2. 处理onreadystatechange事件,规定当服务器响应已做好被处理的准备时所执行的任务
  3. open() 规定请求的类型、URL 以及是否异步处理请求
  4. setRequestHeader() 设置请求头
  5. send() 将请求发送到服务器

createXMLHttp()方法接收一个对象arg 作为参数,返回一个Promise对象。

arg.method:请求的类型
arg.url:请求的url
arg.headers:请求的请求头,以对象形式存储
arg.data:仅用于POST请求
    function createXMLHttp(arg) {
        return new Promise((resolve,reject) => {
            arg = arg || {}
            let xmlhttp;
            if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            } else {// code for IE6, IE5
                //xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4) {
                    if (xmlhttp.status == 200) {
                        var result = xmlhttp.responseText
                        try{
                            resolve(JSON.parse(result))
                        }catch (e) {
                            reject({errorMsg:\'数据格式错误\'})
                        }
                    } else {
                        console.log(\'error:xmlhttp.status =\', xmlhttp.status)
                        reject(xmlhttp)
                    }
                }
            }
            if(Vue.prototype.$ajax.interceptors && Vue.prototype.$ajax.interceptors.request){
                Vue.prototype.$ajax.interceptors.request(arg)
            }
            xmlhttp.open(arg.method || \'GET\', arg.url, true);
            arg.headers = arg.headers || {};
            for (let key in arg.headers){
                xmlhttp.setRequestHeader(key, arg.headers[key]);
            }
         
            xmlhttp.send(arg.data);
        })
    }

封装 post方法

拼接url、处理一下data的格式,调用createXMLHttp创建请求
post的data都是对象形式,处理起来比较简单, body = JSON.stringify(body)就行了

 Vue.prototype.$ajax.post = function post(url,body) {
        url = Vue.prototype.$ajax.baseURL + url;
        body = JSON.stringify(body)
        let token = window.sessionStorage.getItem(\'token\')
        token = (token != \'undefined\') ? JSON.parse(token) : \'\'
        return createXMLHttp({
            method:\'POST\',
            url,
            headers:{
                \'Content-type\':\'application/json;charset=utf-8\',
                \'token\': token
            },
            data:body
        })
    }

封装 get方法

原生AJAX的 GET 请求:

xmlhttp.open("GET","/try/ajax/demo_get.php?t=" + Math.random(),true);
xmlhttp.send();
xmlhttp.open("GET","/try/ajax/demo_get2.php?fname=Henry&lname=Ford",true);
xmlhttp.send();

我的目标是除了上面字符拼接的方式,还能将对象作为参数发送请求

 this.$ajax.get(\'/v1/user\', {
        pageSize:this.pageSize,
        pageNum:this.pageNum
    })
 this.$ajax.get(\'/v1/menuInfo?id=\'+1).then(res =>{})
 this.$ajax.get(\'/v1/menuInfo?id=1&lname=Ford\').then(res =>{})

参数为对象时,要将key:value转为字符串key=value,多个参数中间用&符连接
需要先判断url的最后一位字符是否为\'?\',不是的话,最前面还要补上\'?\'

 let paramsArray = []
 for(let key in params){
     paramsArray.push(key + \'=\' + params[key])
 }
 if(paramsArray.length){
     url = url.indexOf(\'?\') > -1 ? url : (url + \'?\')
     if (url.indexOf(\'?\') != url.length - 1){
         url += \'&\'
     }

     url += paramsArray.join(\'&\')
 }

get方法封装:

Vue.prototype.$ajax.get =  function get(url,params) {
        url = Vue.prototype.$ajax.baseURL + url;

        let paramsArray = []
        for(let key in params){
            paramsArray.push(key + \'=\' + params[key])
        }
        if(paramsArray.length){
            url = url.indexOf(\'?\') > -1 ? url : (url + \'?\')
            if (url.indexOf(\'?\') != url.length - 1){
                url += \'&\'
            }

            url += paramsArray.join(\'&\')
        }
        let token = window.sessionStorage.getItem(\'token\')
        token = (token != \'undefined\') ? JSON.parse(token) : \'\'
        return createXMLHttp({
            method:\'GET\',
            url,
            headers:{
                \'accept\':\'application/json\',
                \'Content-type\':\'application/json;charset=utf-8\',
                \'token\': token
            }
        })
    }

为了方便使用,做成插件vue插件

//./plugin/MyAjax.js
var MyAjax = {};
MyAjax.install = function (Vue) {
    Vue.prototype.$ajax = {
        baseURL:\'xxxxxxxxxxxxxxxxxxxx\'    //服务器域名:端口
    }  
}
module.exports  = MyAjax;
//main.js
import myAjax from \'./plugin/MyAjax\'
Vue.use(myAjax)

请求方式

请求方式和axios差不多

//POST请求
 this.$ajax.post(\'/v1/login\', {
                    userName:this.account,
                    passWord:this.password
                }).then(res =>{
                    // console.log(res)
                
                })
  this.$ajax.post(\'/v1/group\',this.groupInfo).then(res =>{
                 if (!res.error){
                     // this.$router.back()
                 }
             })
//GET请求
  this.$ajax.get(\'/v1/xx?userName=\'this.userName).then(res =>{
                    // console.log(res)             
                })
                   
    this.$ajax.get(\'/v1/user\', {
        pageSize:this.pageSize,
        pageNum:this.pageNum
    }).then(res =>{
        console.log(res)
    })
    
   this.$ajax.get(\'/v1/menuInfo?id=\'+1).then(res =>{})
   this.$ajax.get(\'/v1/menuInfo?id=1&lname=Ford\').then(res =>{})

完整代码

var MyAjax = {};
MyAjax.install = function (Vue) {
    Vue.prototype.$ajax = {
        baseURL:\'xxxxxxxxxxxxxxxxxxxx\'
    }

    function createXMLHttp(arg) {
        return new Promise((resolve,reject) => {
            arg = arg || {}
            let xmlhttp;
            if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            } else {// code for IE6, IE5
                //xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4) {
                    if (xmlhttp.status == 200) {
                        var result = xmlhttp.responseText
                        try{
                            resolve(JSON.parse(result))
                        }catch (e) {
                            reject({errorMsg:\'数据格式错误\'})
                        }

                        // console.log( Vue.prototype.$ajax.result)
                    } else {
                        console.log(\'error:xmlhttp.status =\', xmlhttp.status)
                        reject(xmlhttp)
                    }
                }
            }
            if(Vue.prototype.$ajax.interceptors && Vue.prototype.$ajax.interceptors.request){
                Vue.prototype.$ajax.interceptors.request(arg)
            }
            xmlhttp.open(arg.method || \'GET\', arg.url, true);
            arg.headers = arg.headers || {};
            for (let key in arg.headers){
                xmlhttp.setRequestHeader(key, arg.headers[key]);
            }
            xmlhttp.send(arg.data);
        })
    }

    Vue.prototype.$ajax.get =  function get(url,params) {
        url = Vue.prototype.$ajax.baseURL + url;

        let paramsArray = []
        for(let key in params){
            paramsArray.push(key + \'=\' + params[key])
        }
        if(paramsArray.length){
            url = url.indexOf(\'?\') > -1 ? url : (url + \'?\')
            if (url.indexOf(\'?\') != url.length - 1){
                url += \'&\'
            }

            url += paramsArray.join(\'&\')
        }
        let token = window.sessionStorage.getItem(\'token\')
        token = (token != \'undefined\') ? JSON.parse(token) : \'\'
        return createXMLHttp({
            method:\'GET\',
            url,
            headers:{
                \'accept\':\'application/json\',
                \'Content-type\':\'application/json;charset=utf-8\',
                \'token\': token
            }
        })
    }
    Vue.prototype.$ajax.post = function post(url,body) {
        url = Vue.prototype.$ajax.baseURL + url;
        body = JSON.stringify(body)
        let token = window.sessionStorage.getItem(\'token\')
        token = (token != \'undefined\') ? JSON.parse(token) : \'\'
        return createXMLHttp({
            method:\'POST\',
            url,
            headers:{
                \'Content-type\':\'application/json;charset=utf-8\',
                \'token\': token
            },
            data:body
        })
    }
    Vue.prototype.$ajax.put = function put(url,body) {
        url = Vue.prototype.$ajax.baseURL + url;
        body = JSON.stringify(body)
        let token = window.sessionStorage.getItem(\'token\')
        token = token? JSON.parse(token) : \'\'
        return createXMLHttp({
            method:\'PUT\',
            url,
            headers:{
                \'Content-type\':\'application/json;charset=utf-8\',
                \'token\': token
            },
            data:body
        })
    }
    Vue.prototype.$ajax.DELETE = function DELETE(url,body) {
        url = Vue.prototype.$ajax.baseURL + url;
        body = JSON.stringify(body)
        let token = window.sessionStorage.getItem(\'token\')
        token = token? JSON.parse(token) : \'\'
        return createXMLHttp({
            method:\'DELETE\',
            url,
            headers:{
                \'Content-type\':\'application/json;charset=utf-8\',
                \'token\': token
            },
            data:body
        })
    }
}
module.exports  = MyAjax;

以上是关于原生js 封装ajax请求超详细的主要内容,如果未能解决你的问题,请参考以下文章

原生js封装ajax代码

原生js封装Ajax的GET请求

关于原生ajax请求及其封装

JavaScript原生封装ajax请求和Jquery中的ajax请求,内附详细案例和注释!

Ajax原生请求和java对象转成json

Ajax基础之原生js封装