XMLHttpRequest 是一个内建的浏览器对象,它允许使用 JavaScript 发送 HTTP 请求。
虽然我们已经有了更现代的fetch方法,但是我们需要做一些 fetch 目前无法做到的事情,例如跟踪上传进度

Get请求

一个XMLHttpRequest的使用示例

  1. // 1. 创建一个 new XMLHttpRequest 对象
  2. // 此构造器没有参数
  3. let xhr = new XMLHttpRequest();
  4. // 2. 配置它:从 URL /article/.../load GET-request
  5. // 注意open并不会发送请求
  6. // xhr.open(method, URL, [async, user, password])
  7. xhr.open('GET', '/article/xmlhttprequest/example/load');
  8. // 3. 通过网络发送请求
  9. xhr.send();
  10. // 4. 当接收到响应后,将调用此函数
  11. xhr.onload = function() {
  12. if (xhr.status != 200) { // 分析响应的 HTTP 状态
  13. alert(`Error ${xhr.status}: ${xhr.statusText}`); // 例如 404: Not Found
  14. } else { // 显示结果
  15. alert(`Done, got ${xhr.response.length} bytes`); // response 是服务器响应
  16. }
  17. };
  18. xhr.onprogress = function(event) {
  19. if (event.lengthComputable) {
  20. alert(`Received ${event.loaded} of ${event.total} bytes`);
  21. } else {
  22. alert(`Received ${event.loaded} bytes`); // 没有 Content-Length
  23. }
  24. };
  25. xhr.onerror = function() {
  26. alert("Request failed");
  27. };

一旦服务器有了响应,我们可以在以下 xhr 属性中接收结果:

  • statusHTTP 状态码(一个数字):200,404,403 等,如果出现非 HTTP 错误,则为 0。
  • statusText HTTP 状态消息(一个字符串):状态码为 200 对应于 OK,404 对应于 Not Found,403 对应于 Forbidden。
  • response(旧脚本可能用的是 responseText)服务器 response body。

我们可以使用 xhr.responseType 属性来设置响应格式

  1. xhr.responseType = 'json';

XMLHttpRequest 的状态(state)会随着它的处理进度变化而变化。可以通过 xhr.readyState 来了解当前状态。

  1. UNSENT = 0; // 初始状态
  2. OPENED = 1; // open 被调用
  3. HEADERS_RECEIVED = 2; // 接收到 response header
  4. LOADING = 3; // 响应正在被加载(接收到一个数据包)
  5. DONE = 4; // 请求完成

我们可以使用 readystatechange 事件来跟踪它们:

  1. xhr.onreadystatechange = function() {
  2. if (xhr.readyState == 3) {
  3. // 加载中
  4. }
  5. if (xhr.readyState == 4) {
  6. // 请求完成
  7. }
  8. };

我们可以随时终止请求。调用 xhr.abort() 即可

如果在 open 方法中将第三个参数 async 设置为 false,那么请求就会以同步的方式进行。
换句话说,JavaScript 执行在 send() 处暂停,并在收到响应后恢复执行。这有点儿像 alertprompt 命令

POST请求

要建立一个 POST 请求,我们可以使用内建的 FormData 对象。
语法为:

  1. let formData = new FormData([form]); // 创建一个对象,可以选择从 <form> 中获取数据
  2. formData.append(name, value); // 附加一个字段
  1. let xhr = new XMLHttpRequest();
  2. let json = JSON.stringify({
  3. name: "John",
  4. surname: "Smith"
  5. });
  6. xhr.open("POST", '/submit')
  7. // 设置requestHeader
  8. xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
  9. xhr.send(json);

上传进度

如果我们需要专门跟踪上传,那么我们应该在 xhr.upload 对象上监听相同的事件。

  1. <input type="file" onchange="upload(this.files[0])">
  2. <script>
  3. function upload(file) {
  4. let xhr = new XMLHttpRequest();
  5. // 跟踪上传进度
  6. xhr.upload.onprogress = function(event) {
  7. console.log(`Uploaded ${event.loaded} of ${event.total}`);
  8. };
  9. // 跟踪完成:无论成功与否
  10. xhr.onloadend = function() {
  11. if (xhr.status == 200) {
  12. console.log("success");
  13. } else {
  14. console.log("error " + this.status);
  15. }
  16. };
  17. xhr.open("POST", "/article/xmlhttprequest/post/upload");
  18. xhr.send(file);
  19. }
  20. </script>