Ajax中XMLHttpRequest对象的详细解析

1. XMLHttpRequest对象的相关说明

1.1 XMLHttpRequest对象的特点
  • XMLHttpRequest对象是Ajax技术的核心,XMLHttpRequest使我们可以使用JavaScript向服务器提出请求并处理相应,而不堵塞用户的其他操作
  • 不用刷新整个页面就可以和服务器进行交互式Ajax最大的特点,这个重要的特点主要归功于XMLHttpRequest对象,使用XMLHttpRequest对象使得网页应用程序像windows应用程序一样,能够及时相应用户与服务器之间的交互,不必进行页面的属性或者跳转,并且甭管进行一系列的数据处理,这个功能可以使用户的等待时间缩短,同时也减轻了服务器的负载;
1.2 XMLHttpRequest对象的创建
  • 由于在不同浏览器中,XMLHttpRequest对象的创建方式不同,因此在程序中创建XMLHttpRequest需要对浏览器进行判断
    1) 在Internet Explorer 5(IE5)中

    • XMLHttpRequest实现为一个ActiveX对象,被称为XMLHTTP,它是支持异步请求的技术
    • 创建方式:xmlreq = new ActiveXObject("Microsoft.XMLHTTP");

    2)在Mozilla、Netscape、Safari、Firefox和其他浏览器中

    • XMLHttpRequest被实现为本地的JavaScript对象
    • 创建方式:xmlreq = new XMLHttpRequest();

    3)整合

   function createXMLHttpRequest(){
      var xmlreq=false;
      if(window.ActiveXObject){
        //当为IE5时
        xmlreq=new ActiveXObject('Microsoft.XMLHTTP')
      }else if(window.XMLHTTPRequest){
      	//当为其他浏览器时
        xmlreq=new XMLHttpRequest();
      }
      return xmlreq
    }

代码逻辑说明:
1)首先是在createXMLHttpRequest函数中创建一个变量xmlreq,用来保存这个对象的引用,并将其默认值设置为false;
2)然后使用条件判断语句,根据用户使用的浏览器类型不同,而使用不同的方式来创建XMLHttpRequest对象
3)在条件判断语句中,window.ActiveXObject和window.XMLHTTPRequest都有可能返回null或者一个对象,比如window.ActiveXObject返回null,说明用户使用的不是IE5浏览器,则进入else if中,使用 xmlreq=new XMLHttpRequest();的方式创建XMLHttpRequest对象,反之同理;
4)最后将xmlreq这个对象返回,即完成了XMLHttpRequest对象的创建过程

1.3 XMLHttpRequest对象的属性

XMLHttpRequest兑现提供了许多属性,处理XMLHttpRequest时需要频繁使用到,如下表

属性描述
onreadstatechange每个状态改变时都会触发这个事件的处理处理程序,通常会调用一个JavaScript函数
readyState请求的状态(0-4)
responseText服务器的相应,表示为一个串
responseXML服务器的相应,表示为XML,这个对象可以解析为一个DOM
status服务器的HTTP状态码
statusTextHTTP状态的对应文本
1.3.1 XMLHttpRequest属性的详细说明

属性:

  • 即可以使用xhr.xx的当时调用或者进行设置
1.readyState属性(响应状态)
  • readyState属性表示请求/响应过程的当前活动阶段
  • 当XMLHttpRequest对象将一个HTTP请求发送到服务器会经历若干状态,直到请求被处理,然后所创建的XMLHttpRequest的实例对象才会接收一个响应。这样一来,脚本才能正确的相应各种状态,XMLHttpRequest暴露了一个描述对象状态的属性readyState属性,如下表
readyState的取值描述
0“未初始化”状态,此时XMLHttpRequest 对象已经创建,但是还没有初始化
1描述一种"发送"状态,此时,代码以及调用了XMLHttpRequest对象的open()方法,并且XMLHttpRequest已经准备号把一个请求发送到服务器
2描述一种“发送"状态,此时,已经调用了send()方法,把请求发送给服务器端,只是此时还没有收到一个相应
3描述一种”正在接收“的状态,此时已经接收到HTTP响应头部信息,但是消息体部分还没完全接收结束
4描述一种”已加载“状态,此时,响应已经被完全接受

简洁版:

  • 0:未初始化。以及创建XMLHttpRequest对象,还没调用open()方法
  • 1:启动。已经调用open()方法,但还没有调用send()方法
  • 2:发送。已经调用send()方法,但尚未接收到响应
  • 3:接收。已经接收到响应的部分数据
  • 4:完成。已经接收到响应的全部数据
2.onreadystatechange属性
  • 只要readyState属性的值发送变化,都会触发以此onreadystatechange事件,因此,利用这个事件来检测每次状态发生变化后的readyState的值。
  • 一般清空下,只对readystate值为4的情况做处理,因此此时所有数据都已经就绪;
  • onreadystatechange属性接受一个EventListener值,向该方法只是无论readyState值何时改变,该对象都将激活
    const xhr=new XMLHttpRequest();
    xhr.open('get','/server',true);
    xhr.onreadystatechange=function(){
      if(xhr.readyState!==4){
        return
      }
      if(xhr.status>=200&&xhr.status<300){
        console.log(xhr.responseText)
      }
    }
    xhr.send(null)
3.timeout属性与ontimeout事件
  • timeout属性表示请求在等待响应多少毫秒轴终止,如果在规定时间内没有接收到响应,那么就会触发ontimeout事件处理程序
  const xhr=new XMLHttpRequest()
    xhr.open('get','/server',true);
    //将超市设置为3秒钟
    xhr.timeout=3000;
    //请求超时后请求会自动终止,会调用ontimeout事件处理程序
    xhr.ontimeout=function(){
      //处理代码
      console.log('请求超时了')
    }
    xhr.send(null);
4.overrideMimeType()方法
  • overrideMimeType()方法能够重写服务器返回的MIME类型,从而让浏览器进行不一样的处理。
  • 假如服务器返回的数据类型是text/xml,由于种种原因浏览器解析不成功报错,这时就拿不到数据。为了拿到原始数据,我们可以把MIME类型改成text/plain,这样浏览器就不会去自动解析,从而我们就可以拿到原始文本了。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
xhr.overrideMimeType('text/plain')
xhr.send(null)

5.responseType属性
  • responseType属性是一个字符串,表示服务器返回数据的类型。使用xhr.response属性来接收
  • 这个属性时可写的,可以在调用open()方法之后,send()方法之间设置这个属性值,告诉服务器返回指定类型的数据,如果responseType设为哦空字符串,等同于默认值text。
  • responseTye属性可以设置格式类型如下
responseType属性的值response属性的数据类型与说明
”“String字符串 默认值,等同于text
”text“String字符串 服务器返回文本数据
”document“Document对象 希望返回XML格式数据时使用
”json“javascript对象 IE10/IE11不支持
”blob“Blob对象 服务器返回二进制对象
”arrayBufferArrayBuffer随心 服务器返沪二进制数组
  • 当将reaponseType设置了一个特定类型时,你需要确保服务器返回的类型和你所设置的返回值类型时兼容的。如果两者类型不兼容,那么服务器返回的数据会变成null,及时服务器返回了数据
  • reaponseType只适用于异步请求,如果给同步请求设置了,那么将会抛出InvalidAccessError的异常

    //使用responseTyep,以获取一张图片为例
    const xhr=new XMLHttpRequest();
    xhr.open('get','/server/image.png',true);
    xhr.responseType='blob'//这里返回二进制类型的数据
    xhr.onload=function(){
      if(xhr.status>=200&&xhr.status<300){
        const blob=this.response
        //....
      }
    }
    xhr.send(null)
6.withCredentials属性
  • withCredentials属性是一个布尔值,表示跨域请求是否携带凭据信息(cookie、HTTP认证、以及客户端SSL证明等),默认为false
  • 如果需要跨域Ajax请求发送Cookie,需要withCredentials属性设置为true
  • 如果在同域下配置xhr.withCredentials,无论配置true还是fasle,效果都是一样的
	//配置跨域
    const xhr = new XMLHttpRequest();
    xhr.open('get','/server',true);
    xhr.withCredentials=true;
    xhr.send(null)
  • 当配置了withCredentials为true时,必须在后端增加response头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。
  • 还需要添加Access-Control-Allow-Origin这个头信息为true;
 	//后端配置跨域
    response.addHeader("Access-Control-Allow-Origin", "http://example.com");
    response.addHeader("Access-Control-Allow-Origin", true)
7.response属性
  • response属性表示服务器返回的数据,它可以时任何数据类型,比如字符串、对象、二进制对象等待,具体的类型由XMLHttpRequest.responseType属性决定
  • 如果本次请求没有成功或者数据不完整,该属性等于null
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    console.log(xhr.response)
  }
}
8.responseText属性
  • responseText属性返回从服务器接收到的字符串,该属性为只读
  • 当readyState值为0、1、2时,responseText包含一个空字符串。当readyState值为3时(正在接收),响应中包含客户端还没完成的响应信息;当readyState为4时,此时响应已经完全接收,那么responseText包含完整的响应信息
if (xhr.readyState === 4) {
  if (xhr.status >= 200 && xhr.status < 300) {
    // 处理服务器的返回数据
    console.log(xhr.responseText)
  }
}

9.responseXML属性
  • 如果相应的内容类型时”text/xml“或者”appliction/xml“,这个属性中将保存着包含响应数据的HTML或者XML文档对象;该属性为只读类型
  • 无论内容类型是什么,响应主体的内容都会保存到responseText属性,而对于非XML数据而言,responseXML属性的值将为null
10.responseURL属性

responseURL属性时字符串,表示发送数据的服务器的地址,如果URL为空,则返回空字符串。如果URL有锚点,则位于URL#后面的内容会被删除。如果服务器端发生跳转,这个属性返回最后实际返回数据 的地址

const xhr=new XMLHttpReauest();
xhr.open('GET','http://example.com/test',true);
xhr.onload=function(){
	//返回http://example.com/test
	console.log(xhr.responseURL)
}
xhr.send(null)
11.status属性(HTTP状态码)
  • 这个属性描述了HTTP状态码,属性返回一个整数。同时,当且仅当readyState值为3时(正在接收)和readyState=4时,这个属性才可以使用后。
  • 若在reagyState值小于3时试图取status的值,将会引发一个异常
  • status的值有:200表示成功,404表示为找到资源
if (xhr.readyState === 4) {
  if (xhr.status >= 200 && xhr.status < 300) {
    // 处理服务器的返回数据
  }
}

12.statusText属性
  • statusText属性返回一个字符串,表示服务器发送的状态数目。比如ok和 Not Found。在请求发送之前,该属性的值是一个空字符串,如果服务器没有返回状态提示,该属性默认为欸OK。该属性为只读属性
  • 注意:要通过检测status属性来决定下一步的操作,不要依赖statusText,因为statusText在跨浏览器使用时不太可靠
1.4XMLHTTPRequest对象的方法详细说明
1.4.1.XMLHTTPRequest对象的方法
方法描述
abort()停止当前请求
getAllResponseHeaders()把HTTP请求的所有响应首部作为键/值对返回
getResponseHeader(“header”)返回指定首部的串值
open(“method”,“url”,async)建立与服务器的连接,methos参数可以是GET、POST或者PUT等;url参数时相对的url或者绝对url。
send(content)向服务器发送请求
setRequestHeader(“header”,“value”)把指定的首部设置提供的值,注意:在设置任何首部之前必须在调用open()方法和send()方法之后设置
1.4.2.XMLHttpRequest对象方法的详细使用
1.open()方法-----用于初始化一个请求

open()方法接收三个参数:

  • 第一个参数methos:要发送请求的类型。比如GET、POSE、PYT等。
  • 第二个参数url:请求的URL
  • 第三个参数async:是否异步发送请求的布尔值。true为异步发送请求。
const xhr=new XMLHttpRequest();
xhr.open('get','/userInfo',true)
  • 调用open()
    方法并不会真正的发送请求,而是启动一个琼琼以备发送;
2.send()方法-----用于发送HTTP请求

send()方法接收一个参数:

  • 参数data:作为请求主体发送的数据,如果不需要通过请求主体数据(即不传实际的data时),也必须传入null。
  • 参数data可以接收字符串、FromData(From表单)、Blob、ArrayBuffer等类型数据
const xhr=new XMLHTTPRequest();
xhr.send(null);
3. setRequestHeader()方法
  • setRequestHeader()方法可以设置自定义的请求头部信息
  • 接收两个参数:
    第一个参数header:头部字段的名称
    第二个参数value:头部字段的值
  • 要成功发送请求头部信息。,此方法必须在open()和send()之间调用
const xhr=new XMLHttpRequest();
xhr.open('get','/server',true);
xhr.setRequestHeader('MyHeader','MyValue');
xhr.send(null)
4.abort()方法和onabort事件
  • 在接收响应之前调用abort()方法来取下异步请求。当一个请求被终止后,那么它的readyState属性将被置为0.在终止请求之后,还应该对XMLHttpRequest对象进行解引操作。
  • 当调用abort()之后,会触发onabort事件
    //abort()方法
    const xhr=new XMLHttpRequest();
    xhr.open('get', '/server', true);
    xhr.onabort=function(){
      console.log('请求被终止');
    }
    xhr.send(null);
    //将会调用我们在上面定义的onabort回调函数
    xhr.abort()
1.5 XMLHttpRequest进度事件相关的API
1 onload
  • 当请求成功,接收到完整的现溢数据时触发
  • 可以使用onload事件来替代readtstatechange事件,因为响应接收完毕后将触发onload事件,因此就没有必要检查readyState属性了。只要浏览器接收到服务器的响应,不管其状态如何,都会触发load事件
   //使用onload事件来监听服务器的响应
    const xhr = new XMLHttpRequest();
    //当服务器响应完成时便会触发load事件
    xhr.onload = function onload() {
      console.log('请求数据接收完毕')
      if (xhr.status >= 200 && xhr.status < 300) {
        console.log(xhr.responseText)
      }
    }
    xhr.open('get', '/server', true);
    xhr.send(null);
2.onerror

设置当请求失败时的监听函数

xhr.onerror=function(){
	//
	console.log('请求失败');
}
1.6 请求方式
1.6.1 GET请求
  • 将查询字符串参数追加到URL的末尾,将信息发送给服务器
  • GET参数的编码方式使无法认为干涉的,这导致了不同浏览器有不同的编码方式,因此最稳妥的使人工预编码,人工编码,人工解码,从而禁止浏览器的编码干涉
    //GET请求的人工预编码
    const xhr=new XMLHttpRequest();
    //使用encodeURIComponent()进行编码
    xhr.open('get', '/server', true);
    const temParam=encodeURIComponent('age');
    const temValue=encodeURIComponent('20');
    xhr.open('get','/server?temParam=tempValue&money=100',true)
1.6.2 POST请求
  • POST请求把数据作为请求的主体(请求的body)提交,下面四种常见的PSET请求提交数据方式
    1)application/json
    当发送Ajax请求时,把appliction/json作为请求头,用来告诉服务器消息主体是序列化后的JSON字符串
    2)text/xml
    使用HTTP作为传输协议,XML作为哦编码方式的远程调用规范
    3)application/x-www-form-urlencoded
    浏览器原生form表单,如果不设置enctype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据
    4)multipart/form-data
    表单上传文件时,必须让form表单的enctype等于multipart/form-data

  • 举例如下
    使用XMLHttpRequest模拟表单提交

将Content-Type头部信息设置为application/x-www-form-urlencoded。可以使用XMLHttpRequest对象来模仿表单提交。

const xhr = new XMLHttpRequest()
xhr.open('post', '/server', true)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
const form = document.getElementById('myForm') 
// serialize()为表单序列化方法
xhr.send(serialize(form))

也可以使用XMLHttpRequest level 2的FormData来序列化表单数据。

const xhr = new XMLHttpRequest()
xhr.open('post', '/server', true)
const form = document.getElementById('myForm')
const formData = new FormData(form)
formData.append("id", "123456")
xhr.send(formData)

2.使用Ajax实现异步请求

2.1一般实现
 	//一般实现
    const xhr = new XMLHttpRequest();
    xhr.open('get', '/server', true);
    //设置响应类型
    xhr.responseType = 'json'
    //设置请求头信息
    xhr.setRequestHeader('MyHeader', 'MyValue');
    //设置请求失败监听函数
    xhr.onload = function () {
      console.log('请求失败了...')
    }
    //为XMLHttpRequest对象的状态设置监听事件(监听onreadystatechange)
    xhr.onreadystatechange = function () {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status >= 200 && this.status < 300) {
        //响应正常
        console.log(this.responseText)
      } else {
        console.log(this.statusText)
      }
    }
    //发送请求
    xhr.send(null);
2.2 Promise封装实现

    //Promise封装实现
    function getJSON(url) {
      let promise = new Promise((resolve, reject){
        const xhr = new XMLHttpRequest();
        xhr.open('get', '/server', true);
        //设置响应类型
        xhr.responseType = 'json'
        //设置请求头信息
        xhr.setRequestHeader('MyHeader', 'MyValue');
        //为XMLHttpRequest对象的状态设置监听事件(监听onreadystatechange)
        xhr.onreadystatechange = function () {
          if (this.readyState !== 4) {
            return;
          }
          if (this.status >= 200 && this.status < 300) {
            //响应正常
            // console.log(xhr.responseText)
            resolve(this.responseText)
          } else {
            reject(new Error(this.statusText))
          }
        }
      })
      return promise;
    }

    //使用
    const p1 = getJSON();
    p1.then(
      result => {
        //成功回调,进行相关的数据处理
        console.log(result)
      },
      err => {
        //失败回调
        console.log(err)
      }
    )

用FormData不必明确地在XMLHttpRequest对象上设置请求头部。XMLHttpRequest对象能够识别传入的数据类型是FormData的实例,并配置适当的头部信息。
参考文章:

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
感谢您分享代码!不过看到您的代码有一些错误,我帮您修改一下: 1. 在发送 XMLHttpRequest 请求时,应该将 `xhr.open` 和 `xhr.send` 放在 `if` 语句外面。 2. 将 `var jsonData = JSON.parse(xhr.responseText);` 放在 `if` 语句内部,以避免在请求失败时出现 `jsonData` 未定义的情况。 3. 在 `const username = 'hzx>'` 应该将大于号(>)改为等于号(=)。 4. 在 `buildTree` 函数,应该先将 `tr` 添加到 DOM ,再根据是否有子节点添加子表格。 修改后的代码如下所示: ``` // 根节点ID和名称 var rootId = "N000"; var rootName = "菜单"; // 获取指定节点下的所有子节点 function getChildren(nodes, id) { var result = []; for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.parentIndex === id) { node.children = getChildren(nodes, node.id); result.push(node); } } return result; } // 构建 DOM 树 function buildTree(parentNode, children) { for (var i = 0; i < children.length; i++) { var childNode = children[i]; var tr = $('<tr class="treegrid-' + childNode.id + '"><td>' + childNode.name + '</td></tr>'); parentNode.append(tr); if (childNode.children && childNode.children.length > 0) { var subTable = $('<table></table>'); tr.append(subTable); buildTree($('<tbody></tbody>').appendTo(subTable), childNode.children); } } } // 主程序 const username = 'hzx='; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == XMLHttpRequest.DONE) { if (xhr.status == 200) { var jsonData = JSON.parse(xhr.responseText); var root = { id: rootId, name: rootName, children: getChildren(jsonData, rootId) }; buildTree($('#tree tbody'), root.children); // 初始化 treegrid $('#tree').treegrid({ expanderExpandedClass: 'glyphicon glyphicon-minus', expanderCollapsedClass: 'glyphicon glyphicon-plus' }); } else { alert("请求失败:" + xhr.statusText); } } }; xhr.open("GET", "shouquan.php?username=" + username, true); xhr.send(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值