JavaScript XMLHttpRequest 对象详解:从基础用法到高级特性

作者:纸飞机

时间:2026-11-01

浏览:573

本文深入解析 JavaScript 中的 XMLHttpRequest 对象,涵盖其历史背景、核心属性(如 readyState、responseType)、关键方法(open、send、setRequestHeader)以及各类事件监听机制。通过详细示例展示 GET/POST 请求、文件上传及错误处理,帮助开发者掌握原生 AJAX 通信的核心技术。

文章目录

JavaScript 中的 XMLHttpRequest 对象

XMLHttpRequest 定义

XMLHttpRequest 是一种浏览器内置对象,可用于模拟 HTTP 的 GET 和 POST 请求。结合 JavaScript,它能实现页面数据的无刷新定时更新,在聊天室、文字直播等场景中能带来良好的视觉效果。

简介

浏览器与服务器之间通过 HTTP 协议进行通信。当用户在地址栏输入网址或通过表单提交内容时,浏览器会向服务器发送 HTTP 请求。

1999年,微软在 IE 5.0 中首次引入允许 JavaScript 发起 HTTP 请求的功能。该功能起初未受重视,直到 2004 年 Gmail 和 2005 年 Google Maps 的发布才引发广泛关注。2005 年 2 月,AJAX(Asynchronous JavaScript and XML)一词正式提出,指通过 JavaScript 异步获取 XML 文档并更新网页局部内容,无需刷新整个页面。此后,AJAX 成为脚本发起 HTTP 通信的代名词,W3C 于 2006 年将其定为国际标准。

AJAX 包含以下步骤

  • 创建 XMLHttpRequest 实例
  • 发出 HTTP 请求
  • 接收服务器返回的数据
  • 更新网页数据

AJAX 通过原生的XMLHttpRequest对象发起 HTTP 请求,获取数据后进行处理。目前服务器通常返回 JSON 格式数据,XML 格式已逐渐过时,但“AJAX”一词仍作为通用术语保留,其字面含义已不再严格对应。

XMLHttpRequest对象是 AJAX 的主要接口,用于浏览器与服务器通信。尽管名称中包含XML和Http,它实际上支持多种协议(如file或ftp),并可发送任意格式的数据(包括字符串和二进制)。

XMLHttpRequest本身是一个构造函数,可以使用new命令生成实例。它没有任何参数。
var xhr = new XMLHttpRequest();
一旦新建实例,就可以使用`open()`方法指定建立 HTTP 连接的一些细节。
xhr.open('GET', 'http://www.example.com/page.php', true);
(上面代码指定使用 GET 方法,跟指定的服务器网址建立连接。
第三个参数`true`,表示请求是异步的。)
然后,指定回调函数,监听通信状态(`readyState`属性)的变化。
xhr.onreadystatechange = handleStateChange;
function handleStateChange() {
  // ...
}
(上面代码中,一旦`XMLHttpRequest`实例的状态发生变化,
就会调用监听函数`handleStateChange`)
最后使用`send()`方法,实际发出请求。
xhr.send(null);
(上面代码中,`send()`的参数为`null`,表示发送请求的时候,
不带有数据体。如果发送的是 POST 请求,这里就需要指定数据体。)

获取服务器数据后,AJAX 不会刷新整个网页,仅更新相关部分,从而不中断用户操作。

注意

AJAX 仅能向同源网址(协议、域名、端口均相同)发起 HTTP 请求。若尝试跨域请求,将报错(详见《同源政策》和《CORS 通信》)。

XMLHttpRequest 对象简单用法完整示例

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
  // 通信成功时,状态值为4
  if (xhr.readyState === 4){
    if (xhr.status === 200){
      console.log(xhr.responseText);
    } else {
      console.error(xhr.statusText);
    }
  }
};
xhr.onerror = function (e) {
  console.error(xhr.statusText);
};
xhr.open('GET', '/endpoint', true);
xhr.send(null);

XMLHttpRequest 的实例属性

XMLHttpRequest.readyState

用途:返回一个整数,表示实例对象的当前状态。该属性只读。

返回值说明

0:表示 XMLHttpRequest 实例已生成,但open()方法尚未调用。

1:表示open()方法已调用,但send()方法尚未调用,此时仍可使用setRequestHeader()方法设置 HTTP 请求头信息。

2:表示send()方法已调用,且已收到服务器返回的头信息和状态码。

3:表示正在接收服务器传来的数据体(body 部分)。若responseType属性等于text或空字符串,responseText属性将包含已收到的部分信息。

4:表示服务器返回的数据已完全接收,或本次接收已失败。

通信过程中,每当实例状态变化,readyState属性的值随之改变。每次变化都会触发readyStateChange事件。

var xhr = new XMLHttpRequest();
if (xhr.readyState === 4) {
  // 请求结束,处理服务器返回的数据
} else {
  // 显示提示“加载中……”
}
(上面代码中,`xhr.readyState`等于`4`时,表明脚本发出的
 HTTP 请求已经完成。其他情况,都表示 HTTP 请求还在进行中。)

XMLHttpRequest.onreadystatechange

用途:指向一个监听函数。当readystatechange事件发生(即readyState属性变化)时,执行该函数。

注意

若使用abort()方法终止请求,也会导致readyState属性变化,进而调用XMLHttpRequest.onreadystatechange属性指向的函数。

示例

var xhr = new XMLHttpRequest();
xhr.open( 'GET', 'http://example.com' , true );
xhr.onreadystatechange = function () {
  if (xhr.readyState !== 4 || xhr.status !== 200) {
    return;
  }
  console.log(xhr.responseText);
};
xhr.send();

XMLHttpRequest.response

用途:表示服务器返回的数据体(HTTP 回应的 body 部分)。类型取决于XMLHttpRequest.responseType属性,可能是字符串、对象、二进制对象等。该属性只读。

注意

若请求未成功或数据不完整,该属性等于null。但若responseType属性等于text或空字符串,在请求未结束前(readyState为 3 时),response属性包含服务器已返回的部分数据。

示例

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    handler(xhr.response);
  }
}

XMLHttpRequest.responseType

用途 --- 是一个字符串,表示服务器返回数据的类型。这个属性是可写的,可以在调用open()方法之后、调用send()方法之前,设置这个属性的值,告诉浏览器如何解读返回的数据。如果responseType设为空字符串,就等同于默认值text。

属性可选值

""(空字符串):等同于text,表示服务器返回文本数据。

"arraybuffer":ArrayBuffer 对象,表示服务器返回二进制数组。

"blob":Blob 对象,表示服务器返回二进制对象。

"document":Document 对象,表示服务器返回文档对象。

"json":JSON 对象。

"text":字符串。

上述类型中,text类型适用于大多数情况,且直接处理文本较为方便。document类型适用于返回 HTML/XML 文档的情况,这意味着对于开启 CORS 的网站,可直接用 Ajax 抓取网页,无需解析 HTML 字符串即可进行 DOM 操作。blob类型适用于读取二进制数据,如图片文件。

示例:blob 类型

var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
  if (this.status === 200) {
    var blob = new Blob([xhr.response], {type: 'image/png'});
    // 或者
    var blob = xhr.response;
  }
};
xhr.send();

若将该属性设为ArrayBuffer,即可按数组方式处理二进制数据。

var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
  var uInt8Array = new Uint8Array(this.response);
  for (var i = 0, len = uInt8Array.length; i < len; ++i) {
    // var byte = uInt8Array[i];
  }
};
xhr.send();

若将该属性设为json,浏览器会自动对返回数据调用JSON.parse()方法。即从xhr.response属性(注意,非xhr.responseText属性)获取的不是文本,而是 JSON 对象。

XMLHttpRequest.responseText

用途:返回从服务器接收到的字符串,该属性只读。仅当 HTTP 请求完成接收后,该属性才包含完整数据。

var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.responseType = 'text';
xhr.onload = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseText);
  }
};
xhr.send(null);

XMLHttpRequest.responseXML/JSON

用途:返回从服务器接收到的 HTML 或 XML 文档对象,该属性只读。若请求未成功或数据无法解析为 XML/HTML,该属性等于null。

注意

该属性生效的前提是 HTTP 回应的Content-Type头信息等于text/xml或application/xml。这要求在发送请求前,XMLHttpRequest.responseType属性需设为document。若 HTTP 回应的Content-Type头信息不等于text/xml和application/xml,但希望从responseXML获取数据(即按 DOM 格式解析),需手动调用XMLHttpRequest.overrideMimeType()方法强制进行 XML 解析。

该属性得到的数据是直接解析后的文档 DOM 树。

var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.responseType = 'document';
xhr.overrideMimeType('text/xml');
xhr.onload = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log(xhr.responseXML);
  }
};
xhr.send(null);

XMLHttpRequest.responseURL

用途:字符串,表示发送数据的服务器的网址。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/test', true);
xhr.onload = function () {
  // 返回 http://example.com/test
  console.log(xhr.responseURL);
};
xhr.send(null);

注意

该属性值可能与open()方法指定的请求网址不同。若服务器发生跳转,该属性返回最后实际返回数据的网址。此外,若原始 URL 包含锚点(fragment),该属性会剥离锚点。

XMLHttpRequest.status

用途:返回一个整数,表示服务器回应的 HTTP 状态码。通常通信成功时状态码为 200;若服务器未返回状态码,默认值为 200。请求发出前,该属性为0。该属性只读。

  • 200, OK,访问正常
  • 301, Moved Permanently,永久移动
  • 302, Moved temporarily,暂时移动
  • 304, Not Modified,未修改
  • 307, Temporary Redirect,暂时重定向
  • 401, Unauthorized,未授权
  • 403, Forbidden,禁止访问
  • 404, Not Found,未发现指定网址
  • 500, Internal Server Error,服务器发生错误

具体状态码请阅读:http://t.csdn.cn/w0hY8

只有 2xx 和 304 的状态码表示服务器返回正常状态。

if (xhr.readyState === 4) {
  if ( (xhr.status >= 200 && xhr.status < 300)
    || (xhr.status === 304) ) {
    // 处理服务器的返回数据
  } else {
    // 出错
  }
}

XMLHttpRequest.statusText

用途:返回一个字符串,表示服务器发送的状态提示。不同于status属性,该属性包含完整状态信息,如“OK”和“Not Found”。请求发送前(即调用open()方法前),该属性值为空字符串;若服务器未返回状态提示,默认值为“OK”。该属性只读。

XMLHttpRequest.timeout

用途:返回一个整数,表示多少毫秒后若请求仍未得到结果,将自动终止。若该属性等于 0,表示无时间限制。

XMLHttpRequestEventTarget.ontimeout

用途:用于设置监听函数,若发生 timeout 事件,则执行该函数。

示例

var xhr = new XMLHttpRequest();
var url = '/server';
xhr.ontimeout = function () {
  console.error('The request for ' + url + ' timed out.');
};
xhr.onload = function() {
  if (xhr.readyState === 4) {
    if (xhr.status === 200) {
      // 处理服务器返回的数据
    } else {
      console.error(xhr.statusText);
    }
  }
};
xhr.open('GET', url, true);
// 指定 10 秒钟超时
xhr.timeout = 10 * 1000;
xhr.send(null);

XMLHttpRequest.upload

用途:不仅可发送请求,还可发送文件,即 AJAX 文件上传。发送文件后,通过XMLHttpRequest.upload属性可获得一个对象,观察该对象可得知上传进展。主要方法是监听该对象的各种事件:loadstart、loadend、load、abort、error、progress、timeout。

示例:假定网页上有一个<progress>元素。

<progress min="0" max="100" value="0">0% complete</progress>

文件上传时,对upload属性指定progress事件的监听函数,即可获取上传进度。

function upload(blobOrFile) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/server', true);
  xhr.onload = function (e) {};
  var progressBar = document.querySelector('progress');
  xhr.upload.onprogress = function (e) {
    if (e.lengthComputable) {
      progressBar.value = (e.loaded / e.total) * 100;
      // 兼容不支持 <progress> 元素的老式浏览器
      progressBar.textContent = progressBar.value;
    }
  };
  xhr.send(blobOrFile);
}
upload(new Blob(['hello world'], {type: 'text/plain'}));

事件监听属性

XMLHttpRequest 对象可对以下事件指定监听函数

XMLHttpRequest.onloadstart:loadstart 事件(HTTP 请求发出)的监听函数

XMLHttpRequest.onprogress:progress 事件(正在发送和加载数据)的监听函数

XMLHttpRequest.onabort:abort 事件(请求中止,如用户调用abort()方法)的监听函数

XMLHttpRequest.onerror:error 事件(请求失败)的监听函数

XMLHttpRequest.onload:load 事件(请求成功完成)的监听函数

XMLHttpRequest.ontimeout:timeout 事件(用户指定时限超过,请求未完成)的监听函数

XMLHttpRequest.onloadend:loadend 事件(请求完成,无论成功或失败)的监听函数

示例

xhr.onload = function() {
 var responseText = xhr.responseText;
 console.log(responseText);
 // process the response.
};
xhr.onabort = function () {
  console.log('The request was aborted');
};
xhr.onprogress = function (event) {
  console.log(event.loaded);
  console.log(event.total);
};
xhr.onerror = function() {
  console.log('There was an error!');
};

  progress事件的监听函数有一个事件对象参数,该对象有三个属性:loaded属性返回已传输的数据量,total属性返回总数据量,lengthComputable属性返回布尔值表示加载进度是否可计算。所有监听函数中,仅progress事件的监听函数有参数,其他函数无参数。

注意

若发生网络错误(如服务器无法连通),onerror事件无法获取报错信息。即可能没有错误对象,因此只能显示报错提示。

XMLHttpRequest 的实例方法

XMLHttpRequest.open()

用途:用于指定 HTTP 请求参数,或初始化 XMLHttpRequest 实例对象。

void open(
   string method,
   string url,
   optional boolean async,
   optional string user,
   optional string password
);

参数

    method:表示 HTTP 动词方法,如GET、POST、PUT、DELETE、HEAD等。

    url:表示请求发送目标 URL。

    async:布尔值,表示请求是否异步,默认为true。若设为false,则send()方法需等待服务器返回结果后才进行下一步操作。该参数可选。由于同步 AJAX 请求会导致浏览器失去响应,许多浏览器已禁止在主线程使用,仅允许在 Worker 中使用。因此,该参数轻易不应设为false。

    user:表示用于认证的用户名,默认为空字符串。该参数可选。

    password:表示用于认证的密码,默认为空字符串。该参数可选。

注意

若对已使用open()方法的 AJAX 请求再次调用该方法,等同于调用abort(),即终止请求。

发送 POST 请求示例

var xhr = new XMLHttpRequest();
xhr.open('POST', encodeURI('someURL'));

XMLHttpRequest.send()

用途:用于实际发出 HTTP 请求。参数可选,若不带参数,表示 HTTP 请求仅含 URL 无数据体(典型如 GET 请求);若带参数,表示除头信息外还包含具体数据体(典型如 POST 请求)。

GET 请求示例

var xhr = new XMLHttpRequest();
xhr.open('GET',
  'http://www.example.com/?id=' + encodeURIComponent(id),
  true
);
xhr.send(null);

上述代码中,GET请求的参数作为查询字符串附加在 URL 后面。

发送 POST 请求示例

var xhr = new XMLHttpRequest();
var data = 'email='
  + encodeURIComponent(email)
  + '&password='
  + encodeURIComponent(password);
xhr.open('POST', 'http://www.example.com', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(data);

注意

所有 XMLHttpRequest 的监听事件,都必须在send()方法调用前设定。

  send方法的参数即发送的数据。多种格式数据均可作为其参数。

void send();
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(String data);
void send(FormData data);

若send()发送 DOM 对象,发送前数据会被串行化。若发送二进制数据,建议发送ArrayBufferView或Blob对象,这使得通过 Ajax 上传文件成为可能。

发送表单数据示例

FormData对象可用于构造表单数据。

var formData = new FormData();
formData.append('username', '张三');
formData.append('email', 'zhangsan@example.com');
formData.append('birthDate', 1940);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/register');
xhr.send(formData);

上述代码中,FormData对象构造了表单数据,然后使用send()方法发送。其效果与发送以下表单数据相同。

<form id='registration' name='registration' action='/register'>
  <input type='text' name='username' value='张三'>
  <input type='email' name='email' value='zhangsan@example.com'>
  <input type='number' name='birthDate' value='1940'>
  <input type='submit' onclick='return sendForm(this.form);'>
</form>

以下示例使用FormData对象加工表单数据后发送。

function sendForm(form) {
  var formData = new FormData(form);
  formData.append('csrf', 'e69a18d7db1286040586e6da1950128c');
  var xhr = new XMLHttpRequest();
  xhr.open('POST', form.action, true);
  xhr.onload = function() {
    // ...
  };
  xhr.send(formData);
  return false;
}
var form = document.querySelector('#registration');
sendForm(form);

XMLHttpRequest.setRequestHeader()

用途:用于设置浏览器发送的 HTTP 请求头信息。该方法必须在open()之后、send()之前调用。若多次调用该方法设定同一字段,每次调用的值会被合并为单一值发送。

注意

该方法接受两个参数。第一个参数为字符串,表示头信息的字段名;第二个参数为字段值。

xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
xhr.send(JSON.stringify(data));

上述代码首先设置头信息Content-Type,表示发送 JSON 格式数据;然后设置Content-Length,表示数据长度;最后发送 JSON 数据。

XMLHttpRequest.overrideMimeType()

用途:用于指定 MIME 类型,覆盖服务器返回的真实 MIME 类型,从而让浏览器进行不同处理。例如,若服务器返回数据类型为text/xml,因某些原因浏览器解析失败报错,此时无法获取数据。为获取原始数据,可将 MIME 类型改为text/plain,这样浏览器不会自动解析,从而可获取原始文本。

xhr.overrideMimeType('text/plain')

注意

该方法必须在send()方法前调用。

修改服务器返回的数据类型并非正常情况下的推荐做法。若希望服务器返回指定数据类型,可用responseType属性告知服务器,如下例所示。仅在服务器无法返回某种数据类型时,才使用overrideMimeType()方法。

var xhr = new XMLHttpRequest();
xhr.onload = function(e) {
  var arraybuffer = xhr.response;
  // ...
}
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.send();

XMLHttpRequest.getResponseHeader()

用途:返回 HTTP 头信息指定字段的值,若尚未收到服务器回应或指定字段不存在,返回null。该方法参数不区分大小写。

function getHeaderTime() {
  console.log(this.getResponseHeader("Last-Modified"));
}
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'yourpage.html');
xhr.onload = getHeaderTime;
xhr.send();

注意

若存在多个同名字段,其值会被连接为一个字符串,各字段间使用“逗号+空格”分隔。

XMLHttpRequest.getAllResponseHeaders()

用途:返回一个字符串,表示服务器发来的所有 HTTP 头信息。格式为字符串,各头信息间使用CRLF分隔(回车+换行)。若未收到服务器回应,该属性为null。若发生网络错误,该属性为空字符串。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'foo.txt', true);
xhr.send();
xhr.onreadystatechange = function () {
  if (this.readyState === 4) {
    var headers = xhr.getAllResponseHeaders();
  }
}

上述代码用于获取服务器返回的所有头信息。其可能为以下字符串。

date: Fri, 08 Dec 2017 21:04:30 GMT\r\n
content-encoding: gzip\r\n
x-content-type-options: nosniff\r\n
server: meinheld/0.6.1\r\n
x-frame-options: DENY\r\n
content-type: text/html; charset=utf-8\r\n
connection: keep-alive\r\n
strict-transport-security: max-age=63072000\r\n
vary: Cookie, Accept-Encoding\r\n
content-length: 6502\r\n
x-xss-protection: 1; mode=block\r\n

随后对该字符串进行处理。

var arr = headers.trim().split(/[\r\n]+/);
var headerMap = {};
arr.forEach(function (line) {
  var parts = line.split(': ');
  var header = parts.shift();
  var value = parts.join(': ');
  headerMap[header] = value;
});
headerMap['content-length'] // "6502"

XMLHttpRequest.abort()

用途:用于终止已发出的 HTTP 请求。调用此方法后,readyState属性变为4,status属性变为0。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.example.com/page.php', true);
setTimeout(function () {
  if (xhr) {
    xhr.abort();
    xhr = null;
  }
}, 5000);

上述代码在发出 5 秒后终止一个 AJAX 请求。

XMLHttpRequest 实例的事件

readyStateChange 事件

readyState属性值发生改变时,触发 readyStateChange 事件。

可通过onReadyStateChange属性指定该事件的监听函数,对不同状态进行不同处理。特别是当状态变为4时,表示通信成功,此时回调函数可处理服务器传送回来的数据。

progress 事件

上传文件时,XMLHttpRequest 实例对象本身及实例的upload属性均有progress事件,会不断返回上传进度。

var xhr = new XMLHttpRequest();
function updateProgress (oEvent) {
  if (oEvent.lengthComputable) {
    var percentComplete = oEvent.loaded / oEvent.total;
  } else {
    console.log('无法计算进展');
  }
}
xhr.addEventListener('progress', updateProgress);
xhr.open();

load 事件、error 事件、abort 事件

load 事件表示服务器传来的数据接收完毕,error 事件表示请求出错,abort 事件表示请求被中断(如用户取消请求)。

var xhr = new XMLHttpRequest();
xhr.addEventListener('load', transferComplete);
xhr.addEventListener('error', transferFailed);
xhr.addEventListener('abort', transferCanceled);
xhr.open();
function transferComplete() {
  console.log('数据接收完毕');
}
function transferFailed() {
  console.log('数据接收出错');
}
function transferCanceled() {
  console.log('用户取消接收');
}

loadend 事件

abort、load和error这三个事件,会伴随一个loadend事件,表示请求结束,但不知是否成功。

xhr.addEventListener('loadend', loadEnd);
function loadEnd(e) {
  console.log('请求结束,状态未知');
}

timeout 事件

服务器超过指定时间仍未返回结果时,触发 timeout 事件,具体示例参见timeout属性一节。

Navigator.sendBeacon()

用户卸载网页时,有时需向服务器发送数据。自然的做法是在unload事件或beforeunload事件的监听函数中,使用XMLHttpRequest对象发送数据。但这样做可靠性不高,因为XMLHttpRequest对象是异步发送,可能在即将发送时页面已卸载,导致发送取消或失败。

解决方法:在unload事件中加入一些耗时的同步操作,从而留出足够时间保证异步 AJAX 发送成功。

function log() {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/log', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('foo=bar');
}
window.addEventListener('unload', function(event) {
  log();
  // a time-consuming operation
  for (let i = 1; i < 10000; i++) {
    for (let m = 1; m < 10000; m++) { continue; }
  }
});

上述代码中,强制执行了一次双重循环,延长了unload事件的执行时间,导致异步 AJAX 得以成功发送。

类似地还可使用setTimeout。以下是追踪用户点击的例子

// HTML 代码如下
// <a id="target" href="https://baidu.com" rel="external nofollow" >click</a>
const clickTime = 350;
const theLink = document.getElementById('target');
function log() {
  let xhr = new XMLHttpRequest();
  xhr.open('post', '/log', true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('foo=bar');
}
theLink.addEventListener('click', function (event) {
  event.preventDefault();
  log();
  setTimeout(function () {
    window.location.href = theLink.getAttribute('href');
  }, clickTime);
});

上述代码使用setTimeout,拖延了 350 毫秒才让页面跳转,从而使异步 AJAX 有时间发出。

共同问题

卸载时间被强行延长,后续页面加载被推迟,用户体验不佳。

解决问题

为解决此问题,浏览器引入了Navigator.sendBeacon()方法。该方法仍异步发出请求,但请求与当前页面线程脱钩,作为浏览器进程任务,因此可保证数据发出,不拖延卸载流程。

window.addEventListener('unload', logData, false);
function logData() {
  navigator.sendBeacon('/log', analyticsData);
}

Navigator.sendBeacon方法接受两个参数,第一个参数为目标服务器 URL,第二个参数为可选发送数据(字符串、表单对象、二进制对象等)。

navigator.sendBeacon(url, data)
这个方法的返回值是一个布尔值,成功发送数据为true,否则为false。
该方法发送数据的 HTTP 方法是 POST,可以跨域,类似于表单提交数据。它不能指定回调函数。

示例

// HTML 代码如下
// <body onload="analytics('start')" onunload="analytics('end')">
function analytics(state) {
  if (!navigator.sendBeacon) return;
  var URL = 'http://example.com/analytics';
  var data = 'state=' + state + '&location=' + window.location;
  navigator.sendBeacon(URL, data);
}

到此这篇关于 JS——XMLHttpRequest 对象的文章就介绍到这了,更多相关 JS XMLHttpRequest 对象内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章