跳至主要內容

AJAX

wzCoding大约 6 分钟JavaScriptAJAX

AJAX

AJAX并非编程语言,而是一种使用现有技术集合的方法。这些技术包括 HTMLXHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。AJAX的全称为 Asynchronous JavaScript And XML,意为异步JavaScript和XML

AJAX是如何工作的

AJAX的工作方式是在后台与服务器进行少量数据交换,这使得网页可以在不重新加载整个网页的情况下,对网页的某部分进行更新。这种技术在浏览器运行,使用浏览器与web服务器之间的异步数据传输,使网页从服务器请求少量的信息,而不是整张页面

XMLHttpRequest

XMLHttpRequest是AJAX的基础,也是最核心的部分,它是一个内置对象,允许我们使用 JavaScript 发送 HTTP 请求,虽然它的名字里面有 XML 一词,但它可以操作任何数据,而不仅仅是 XML 格式。我们可以用它来上传/下载文件,跟踪请求进度等

创建 XHR 对象

const xhr = new XMLHttpRequest();

初始化请求

xhr.open(method, URL, [async, user, password]);

open 方法有三个参数:

  • method:请求的类型;包含 GETPOSTPUTDELETE
  • URL:一个 url 字符串,表示请求的地址
  • async:一个可选的布尔参数,表示是否异步执行操作,默认为 true。如果值为 falsesend() 方法直到收到答复前不会返回
  • user、password:可选的用户名和密码,用于身份验证用途,默认为 null

设置请求头

XMLHttpRequest 允许发送自定义 header,并且可以从响应中读取 headerheader 必须在 open() 之后 send() 之前设置

//xhr.setRequestHeader(header, value);
xhr.setRequestHeader('Content-Type', 'application/json');

setRequestHeader 方法用于设置请求头,它有两个参数:

  • header:请求头的名称
  • value:请求头的值

header 会以单行的形式返回,header 之间的换行符为 \r\n,并且 header 的 namevalue 之间总是用以冒号后跟一个空格 : 来分隔,获取header的方法有两种:

  • xhr.getResponseHeader(name):获取给定名称的响应头
  • xhr.getAllResponseHeaders():获取所有响应头
Cache-Control: max-age=31536000
Content-Length: 2480
Content-Type: application/json
Date: Sat, 09 Sep 2023 16:53:16 GMT

当想要将获取到的 header 处理成为可用的对象,需要额外使用一些JS方法来处理:

const headers = xhr
  .getAllResponseHeaders()
  .split('\r\n')
  .reduce((result, current) => {
    let [name, value] = current.split(': ');
    result[name] = value;
    return result;
  }, {});

这样就可以获得一个标准的 header 对象了

设置请求超时

xhr.timeout = 3000;

超时设置会在请求耗时超过给定的超时事件后,自动终止请求,并将 readyState 属性设置为 4,同时触发 timeout 事件

设置响应类型

xhr.responseType = 'json';

responseType 属性用于设置响应的数据类型,它接受以下值:

  • '':空字符串,默认值,代表响应的数据类型为 text
  • 'text':代表响应的数据类型为 text
  • 'arraybuffer':代表响应的数据类型为 ArrayBuffer
  • 'blob':代表响应的数据类型为 Blob
  • 'document':代表响应的数据类型为 Document
  • 'json':代表响应的数据类型为 JSON
  • 'text':代表响应的数据类型为 text

发送请求

xhr.send([body]);

send 方法有一个可选的参数 [body],它的默认值是 null,它还可以取以下的值:

  • 可以为 Document, 在这种情况下,它在发送之前被序列化
  • 可以为 XMLHttpRequestBodyInit, Blob,BufferSource, FormData, URLSearchParams, 或者 USVString 对象

XHR 请求状态

XMLHttpRequest.status 代表了 xhr 请求的状态。status 的值是一个无符号的数字类型。在请求完成前,status 的值为 0。如果请求出错,浏览器返回的 status 也为 0。status 码是标准的 HTTP status code

常见的 HTTP status code 请看文章最后

XHR 事件监听

//监听 XHR 加载事件
xhr.onload = function(){
    console.log(`status: ${xhr.status}`);
    console.log(xhr.response);
}
//监听 XHR 错误事件
xhr.onerror = function(){
    console.log('Request failed');
}
//监听 XHR 加载进度事件
xhr.onprogress = function(event){
// event.loaded —— 已经下载了多少字节
// event.lengthComputable = true,当服务器发送了 Content-Length header 时
// event.total —— 总字节数(如果 lengthComputable 为 true)
console.log(`Received ${event.loaded} of ${event.total} bytes`);
}

在 xhr 对象上,上面示例中的3个事件是最常用的:

  • load 事件:请求成功完成时触发
  • error 事件:请求失败时触发,例如网络中断或者无效的 URL
  • progress 事件:请求接收到更多数据时触发,可以获取到请求进度

XHR 状态监听

xhr 对象的状态会随着它的处理进度的变化而变化,xhr 对象提供了 readyState 属性,用来表示它的请求状态,它有5个可能的值:

  • 0:请求未初始化(UNSENT)
  • 1:服务器连接已建立(OPENED)
  • 2:请求已接收(HEADER_RECEIVED)
  • 3:请求处理中(LOADING)
  • 4:请求已完成,且响应已就绪(DONE)

readyState 属性的值发生变化时,会触发 readystatechange 事件:

xhr.onreadystatechange = function(){
    if(xhr.readyState === 4){
        if(xhr.status >= 200 && xhr.status < 300){
            console.log(xhr.responseText);
        } else {
            console.log(`Error: ${xhr.status}`);
        }
    }
}

跟踪上传进度

在上面的示例中,我们介绍了 onprogress 事件,它用来监听请求(下载)的进度,但是有时我们在上传文件时,也会想要监听上传的进度,这时可以使用 xhr.upload 对象来进行监听

xhr.upload 对象有以下事件,会在不同的上传阶段触发:

  • loadstart:上传开始时触发
  • progress:上传过程中不断触发
  • abort:上传被中断时触发
  • error:上传失败时触发
  • load:上传成功完成时触发
  • loadend:上传完成时触发
  • timeout:上传超时触发(如果设置了 timeout 属性)
// 监听上传进度
xhr.upload.onprogress = function(event){
    if(event.lengthComputable){
        console.log(`Received ${event.loaded} of ${event.total} bytes`);
    }
}
// 监听上传完成
xhr.upload.onload = function() {
  console.log(`Upload finished successfully.`);
}
// 监听上传失败
xhr.upload.onerror = function() {
  console.log(`Error during the upload: ${xhr.status}`);
}
// 监听上传中断
xhr.upload.onabort = function() {
  console.log(`The upload has been aborted`);
}

终止 XHR 请求

xhr.abort();

abort 方法会终止请求,并将 xhr 的 readyState 属性与 status 重置为 0

常见状态码

状态类型描述
100信息响应Continue(继续)。客户端应继续其请求
101信息响应Switching Protocols(切换协议)。服务器根据客户端的请求切换协议
200成功响应OK。请求成功。一般用于GET与POST请求
201成功响应Created。成功请求并创建了新的资源
204成功响应No Content。服务器成功处理,但未返回内容
301重定向Moved Permanently。请求的资源已被永久的移动到新URI
302重定向Found。此响应代码表示所请求资源的URI已暂时更改
400客户端错误Bad Request。客户端请求的语法错误,服务器无法理解
401客户端错误Unauthorized。请求要求用户的身份认证
403客户端错误Forbidden。服务器理解请求客户端的请求,但是拒绝执行此请求
404客户端错误Not Found。服务器无法根据客户端的请求找到资源(网页等)
500服务器错误Internal Server Error。服务器内部错误,无法完成请求
502服务器错误Bad Gateway。作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503服务器错误Service Unavailable。由于超载或系统维护,服务器暂时的无法处理客户端的请求
ℹ️提示

更多关于 AJAX 的信息,请参考 XMLHTTPRequest