XMLHttpRequest(XHR)简介

2025-06-08

XMLHttpRequest(XHR)简介

这篇文章最初发表在attacomsian.com/blog上。


XMLHttpRequest (XHR) 由微软于 20 世纪 90 年代初发明,并在 21 世纪第一个十年中期成为异步服务器交互的首选技术。

得益于 XHR,我们第一次可以在不重新加载整个页面的情况下更新网页的部分内容。

XMLHttpRequest是所有现代浏览器中的内置浏览器对象,可用于在 JavaScript 中发出 HTTP 请求以在 Web 浏览器和服务器之间交换数据。

尽管名称中带有“XML”一词,但它XMLHttpRequest可以用于检索任何类型的数据,而不仅仅是XML。我们可以使用它来上传/下载文件、提交表单数据、跟踪进度等等。

基本 XHR 请求

要使用 XHR 发送 HTTP 请求,请创建一个XMLHttpRequest对象,打开与 URL 的连接,然后发送请求。请求完成后,该对象将包含有用的信息,例如响应主体和 HTTP 状态代码。

让我们使用JSONPlaceholder测试 REST API 来通过 XHR 发送 GET 请求:

// create an XHR object
const xhr = new XMLHttpRequest();

// listen for `onload` event
xhr.onload = () => {
    // process response
    if (xhr.status == 200) {
        // parse JSON data
        console.log(JSON.parse(xhr.response));
    } else {
        console.error('Error!');
    }
};

// create a `GET` request
xhr.open('GET', 'https://jsonplaceholder.typicode.com/users');

// send request
xhr.send();

xhr.onloadevent 仅适用于现代浏览器(IE10+、FireFox、Chrome、Safari)。如果您想支持旧版浏览器,请使用xhr.onreadystatechangeevent。

xhr.open()方法

在上面的示例中,我们将 HTTP 方法和 URL 传递给了请求 toopen()方法。此方法通常在 之后立即调用new XMLHttpRequest()。我们可以使用此方法指定请求的主要参数:

该方法的语法如下:

xhr.open(method, URL, [async, user, password])
  • method— HTTP 请求方法。可以是GETPOST、 等DELETEPUT
  • URL— 请求的 URL,字符串或URL 对象
  • asnyc— 指定请求是否异步进行。默认值为true
  • username& password——基本 HTTP 身份验证的凭证

open()方法不会打开与 URL 的连接。它仅配置 HTTP 请求。

xhr.send()方法

xhr.send([body])

send()方法会打开网络连接并向服务器发送请求。它接受一个body包含请求主体的可选参数。对于像 这样的请求方法,GET您无需传递 body 参数。

XHR 事件

最广泛使用的三种 XHR 事件如下:

  • load— 当结果准备就绪时调用此事件。它相当于xhr.onreadystatechange带有 的事件xhr.readyState == 4
  • error— 当由于网络故障或 URL 无效而导致请求失败时,会触发此事件。
  • progress— 此事件在响应下载期间定期触发。它可用于报告大型网络请求的进度。
// listen for `load` event
xhr.onload = () => {
    console.log(`Data Loaded: ${xhr.status} ${xhr.response}`);
};

// listen for `error` event
xhr.onerror = () => {
    console.error('Request failed.');
}

// listen for `progress` event
xhr.onprogress = (event) => {
    // event.loaded returns how many bytes are downloaded
    // event.total returns the total number of bytes
    // event.total is only available if server sends `Content-Length` header
    console.log(`Downloaded ${event.loaded} of ${event.total}`);
}

请求超时

您可以通过指定毫秒的时间轻松配置请求超时:

// set timeout
xhr.timeout = 5000; // 5 seconds

// listen for `timeout` event
xhr.ontimeout = () => console.log('Request timeout.', xhr.responseURL);

xhr.responseURL属性返回实例在完成所有重定向后的最终 URL XMLHttpRequest。这是检索标头的唯一方法Location

响应类型

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

  • 空(默认)或text纯文本
  • json— 解析后的 JSON
  • blob— 二进制数据 Blob
  • document— XML 文档
  • arraybufferArrayBuffer对于二进制数据

让我们调用 RESTful API 来获取 JSON 格式的响应:

const xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.jsonbin.io/b/5d5076e01ec3937ed4d05eab/1');

// set response format
xhr.responseType = 'json';

xhr.send();

xhr.onload = () => {
    // get JSON response
    const user = xhr.response;

    // log details
    console.log(user.name); // John Doe
    console.log(user.email); // john.doe@example.com
    console.log(user.website); // http://example.com
}

请求状态(xhr.readyState

对象XMLHttpRequest的状态会随着请求的进行而改变。我们可以使用xhr.readyState属性访问当前状态。

这些州是:

  • UNSENT(0)——初始状态
  • OPENED(1)— 请求开始
  • HEADERS_RECEIVED(2) — 收到的 HTTP 标头
  • LOADING(3)— 响应正在加载
  • DONE(4)— 请求已完成

我们可以使用事件来跟踪请求状态onreadystatechange

xhr.onreadystatechange = function () {
    if(xhr.readyState == 1) {
        console.log('Request started.');
    }

    if(xhr.readyState == 2) {
        console.log('Headers received.');
    }

    if (xhr.readyState == 3) {
        console.log('Data loading..!');
    }
    if (xhr.readyState == 4) {
        console.log('Request ended.');
    }
};

中止请求

abort()我们可以随时通过调用对象上的方法轻松中止 XHR 请求xhr

xhr.abort(); // cancel request

同步请求

默认情况下,XHR 会发出异步请求,这有利于提高性能。但是,如果您想显式地发出同步请求,只需将false第三个参数传递给open()方法即可。它会暂停 JavaScript 执行,send()并在响应可用时恢复执行:

xhr.open('GET', 'https://api.jsonbin.io/b/5d5076e01ec3937ed4d05eab/1', false);

注意! Chrome 会对同步 XHR 请求显示以下警告:[弃用] 主线程上的同步 XMLHttpRequest 已被弃用,因为它会对最终用户的体验产生不利影响。

HTTP 标头

XMLHttpRequest允许我们设置请求头以及读取响应头。我们可以通过调用对象上的方法来设置请求头Content-Type和响应头AcceptsetRequestHeader()xhr

// set request headers
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', '*/*'); // accept all

类似地,如果您想读取响应头(除Set-Cookie),请getResponseHeader()调用xhr对象:

// read response headers
xhr.getResponseHeader('Content-Type');
xhr.getResponseHeader('Cache-Control');

想要立即获取响应头?请使用getAllResponseHeaders()

xhr.getAllResponseHeaders();

XHR POST 请求

XMLHttpRequest提交表单数据的 POST 请求可以通过两种方式发送

  1. 仅使用 Ajax
  2. 使用FormDataAPI

第一种方法已经足够好了,除非您要上传文件并需要multipart/form-data编码。以下是如何使用 URL 编码的表单数据发出 POST 请求:

const xhr = new XMLHttpRequest();

// configure a `POST` request
xhr.open('POST', '/login');

// prepare form data
let params = 'username=attacomsian&password=123456';

// set `Content-Type` header
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

// pass `params` to `send()` method
xhr.send(params);

// listen for `load` event
xhr.onload = () => {
   console.log(xhr.responseText);
}

想要发起 JSON POST 请求吗?请确保使用JSON.stringify()将 JSON 数据转换为字符串,并将Content-Type标头设置为application/json

const xhr = new XMLHttpRequest();

// configure a `POST` request
xhr.open('POST', '/login');

// create a JSON object
const json = {
    username: 'attacomsian',
    password: '123456'
};

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

// pass `params` to `send()` method
xhr.send(JSON.stringify(params));

// listen for `load` event
xhr.onload = () => {
   console.log(xhr.responseText);
}

跨域请求和 Cookie

XMLHttpRequest可以发送跨域请求,但需要遵守特殊的安全措施。要从其他服务器请求资源,服务器必须使用 CORS(跨域资源共享)明确支持此功能。

与Fetch API类似,XHR 不会向其他来源发送 Cookie 和 HTTP 授权。要发送 Cookie,可以使用对象withCredentials的属性xhr

xhr.withCredentials = true;

XHR 与 jQuery

jQuery 包装器方法$.ajax()在底层使用了 XHR,并提供了更高级别的抽象,以简化开发人员的工作。使用 jQuery,我们可以将上面的代码简化为几行:

$.ajax('https://jsonplaceholder.typicode.com/users')
    .done(data => {
        console.log(data);
    }).fail(err => {
        console.error('Error:', err);
    });

XHR 与 Fetch API 对比

Fetch API基于 Promise 的XHR 现代替代方案。它简洁、易懂,并且在PWA Service Workers中被广泛使用。

上面的 XHR 示例可以转换为更简单的fetch()基于 的代码,甚至可以自动解析返回的 JSON:

fetch('https://jsonplaceholder.typicode.com/users')
    .then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error('Error:', err));

✌️ 我撰写有关现代 JavaScript、Node.js、Spring Boot以及所有Web 开发方面的文章。订阅我的新闻通讯,每周获取 Web 开发教程和专业技巧。


喜欢这篇文章吗? 请在 Twitter 上关注 @attacomsian。你也可以在LinkedInDEV上关注我。

鏂囩珷鏉ユ簮锛�https://dev.to/attacomsian/introduction-to-xmlhttprequest-xhr-142j
PREV
JavaScript 中的地图
NEXT
JavaScript 正则表达式简介