JS之AJAX-XHR对象

AJAX是Asynchronous JavasSript And XML的简写,这项技术能够在不卸载页面的情况下发出HTTP请求,虽然名字中包含XML,但AJAX通信与数据格式无关

AJAX通信通常包含4个步骤:

  1. 创建XMLHttpRequest对象
  2. 发送HTTP请求
  3. 接收服务器返回的数据
  4. 更新网页数据

创建

AJAX技术的核心是XMLHttpRequest对象(简称XHR),可以直接使用new关键字实例化一个XHR对象

var xhr = new XMLHttpRequest()

注意: 如果要建立N个不同的请求,理论上需要使用N个不同的XHR对象。如果重用已存在的XHR对象,会终止之前通过该对象挂起的任何请求

发送请求

open()

XHR对象的open()方法用于发送请求,该方法接收三个参数:请求方式、请求地址和一个布尔值

xhr.open("GET","/api/test", true);

请求方式:请求方式比较常用的是GET和POST,也可以是PATCH、DELETE、OPTIONS等。这个字符串是不区分大小写的,但通常使用大写字母。

请求地址:请求地址通常是相对于执行代码的当前页面。如果需要发出跨域请求,后端要支持CORS,否则会报错

布尔值:布尔值表示是否异步发送请求的布尔值,默认为true,表示异步发送

其他:如果请求一个受密码保护的URL,可以把用于认证的用户名和密码作为第4和第5个参数传递给open()方法

send()

open()方法调用后,必须执行send()方法才会真正发送请求。如果是GET方式,send()方法无参数,或参数为null;如果是POST方式,send()方法的参数为要发送的数据

xhr.open('GET', 'https://www.86886.wang/api/tags', true); 
xhr.send(null);

接收响应

一个完整的HTTP请求由响应状态码、响应头集合和响应主体组成。在收到响应后,这些都可以通过XHR对象的属性和方法使用,主要有以下4个属性

responseText:    作为响应主体被返回的文本(文本形式)
responseXML:     如果响应的内容类型是'text/xml'或'application/xml',这个属性中将保存着响应数据的XML DOM文档(document形式)
status:          HTTP状态码(数字形式),比如200
statusText:      HTTP状态说明(文本形式),比如OK

在接收到响应后,第一步是检测status状态,HTTP状态码为200表示请求成功,此时responseText属性的内容已经就绪。另外状态码304表示资源没有被修改,可以直接从浏览器缓存获取,这个响应也是有效的

无论内容类型是什么,响应主体的内容都会保存到responseText属性中。对于非XML数据而言(如JSON),responseXML属性的值将为null

if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
  console.log(xhr.responseText);
}else{
  console.log('Request fail:' + xhr.status);
}

同步请求

把open()方法的第三个参数设置为false,表示是同步请求,此时send()方法将会阻塞直到请求完成。由于JS是单线程的,所以会导致整个浏览器UI冻结,如果连接的服务器响应慢,那么用户的浏览器将冻结

开发中要避免使用同步请求,下面是同步请求的示例

<div id="result"></div>
<button id="btn">GET同步请求</button>
<script>
  btn.onclick = function() {
    var data = ajax();
    result.innerHTML = data;
  }
  function ajax() {
    var xhr = new XMLHttpRequest();
    if(xhr.readyState == 4) {
      if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
        return xhr.responseText;
      }
    }
    // 同步请求
    xhr.open('GET', 'https://www.86886.wang/api/tags', false);
    xhr.send();
  }
</script>

异步请求

异步请求需要检测XHR对象的readyState属性,该属性表示请求/响应过程的当前活动阶段,取值如下:

0(UNSENT):未初始化。尚未调用open()方法
1(OPENED):启动。已经调用open()方法,但尚未调用send()方法
2(HEADERS_RECEIVED):发送。己经调用send()方法,且接收到头信息
3(LOADING):接收。已经接收到部分响应主体信息
4(DONE):完成。已经接收到全部响应数据,而且已经可以在客户端使用了

只要readyState属性值发生变化,就会触发onreadystatechange事件,通常只需要对值为4时做判断,此时表示数据已经准备就绪

注意: 必须在调用open()之前指定onreadystatechange 事件处理程序才能确保跨浏览器兼容性,否则将无法接收readyState属性为0和1的情况

异步请求示例

<div id="result"></div>
<button id="btn">GET异步请求</button>
<script>
  btn.onclick = function() {
    ajax(function(data) {
      result.innerHTML = data;
    });
  }
  function ajax(cb) {
    var xhr = new XMLHttpRequest();
    // 异步请求
    xhr.onreadystatechange = function() {
      if(xhr.readyState == 4) {
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
          cb(xhr.responseText);
        }
      }
    }
    xhr.open('GET', 'https://www.86886.wang/api/tags', true);
    xhr.send();
  }
</script>

超时

XHR对象有一个timeout属性,表示多少毫秒后,如果请求仍然没有得到结果就会自动终止。默认值0,表示没有限制

如果请求超时,会触发ontimeout事件

function ajax(cb) {
  var xhr = new XMLHttpRequest();
  // 异步请求
  xhr.onreadystatechange = function() {
    if(xhr.readyState == 4) {
      if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
        cb(xhr.responseText);
      }
    }
  }
  xhr.open('GET', 'https://www.86886.wang/api/tags', true);
  xhr.ontimeout = function() {
    console.log('The request timed out.');
  }
  xhr.timeout = 5000; // 5s
  xhr.send();
}
posted @ 2021-09-29 14:04  wmui  阅读(410)  评论(0编辑  收藏  举报