XMLHTTPRequest
定义
XMLHTTPRequest 是浏览器向脚本开放的一个对象,属于 Web API 的组成部分,作用是让页面代码按需与服务器交换数据。它的使用以一个构造出来的对象实例为单位,通过指定请求方法、地址和是否异步,把 HTTP 请求发给服务器[1]。服务器返回后,响应正文、HTTP 状态码和响应标头都可以从该对象的属性或方法中读取[2]。
名称中的 XML 只反映它诞生时主要传输 XML 文档的事实,接口本身并不限定数据格式,文本、二进制、JSON 文档都能接收[2]。按照 WHATWG 的定义,该接口在窗口、专用工作线程和共享工作线程中都可以使用,服务工作者中不可用[1]。
原理
一次典型的 XHR 交互分为创建对象、打开请求、发送请求和处理响应几个阶段。构造对象并调用 open() 时传入方法与地址,此时可以调用 setRequestHeader() 补充请求标头;调用 send() 后请求才真正发出,若为异步模式,send() 在发出后立即返回,结果通过事件回调交付[1]。
对象用一个只读的 readyState 属性表示所处阶段,取值 0 到 4,依次对应未发送、已打开、已收到标头、正在下载和完成这几种状态;每次取值变化都会触发 readystatechange 事件[3]。可以用状态机近似描述这一流转:
$\text{UNSENT}(0) \to \text{OPENED}(1) \to \text{HEADERS\_RECEIVED}(2) \to \text{LOADING}(3) \to \text{DONE}(4)$[3]
响应一侧由若干属性构成:status 给出 HTTP 状态码,statusText 给出状态描述文字,response 按 responseType 的设定返回字符串、文档、二进制缓冲或 JavaScript 对象等不同类型的数据,responseXML 则在响应可解析时提供文档对象[1]。请求过程中还会派发 loadstart、progress、load、error、abort、timeout 和 loadend 等事件,可用于显示传输进度或处理失败情形[2]。
发展历程
这一能力由微软的 Outlook Web Access 团队提出,最初在 1998 年前后作为脚本对象出现在 Outlook Web Access 项目中,随后以 XMLHTTP 的名称随 MSXML 库一起发布,并通过 ActiveX 控件的形式在 Internet Explorer 5 中提供给开发者[4]。此后其他浏览器厂商各自实现了功能相近的 JavaScript 对象,并沿用 XMLHttpRequest 这一名称[4]。微软自 Internet Explorer 7 起改为提供原生的 XMLHttpRequest 对象[4]。
2005 年 2 月,Jesse James Garrett 在一篇文章中用 Ajax 一词概括这种不刷新页面即可与服务器交换数据的开发方式,XHR 由此获得广泛关注[4]。万维网联盟于 2006 年 4 月 5 日发布该对象的第一份工作草案,2008 年 2 月 25 日又发布第二级规范草案,后者增加了进度事件监控、跨站请求和字节流处理等内容[5]。第二级规范在其后并入原规范,2012 年底起改由 Web 超文本应用技术工作小组以持续更新的活动标准形式维护[5]。
应用
最常见的使用场景是局部刷新:页面只向服务器取回一小块数据,再交由脚本更新对应区域,用户不必等待整页重新载入[1]。表单提交、列表分页、搜索建议、消息轮询等交互都可以建立在这一机制上,早期的大型在线应用如 Outlook Web Access、Gmail 和 Google 地图均大量使用了这种后台请求方式[4]。
借助 responseType 的设定,同一接口也能处理非文本内容,例如把远程数据读入二进制缓冲区以便解析图片或音视频[2]。上传过程由 upload 属性单独暴露,可对上行数据同样进行进度监听[1]。在需要持续接收服务器推送或进行全双工通信时,规范建议改用服务器发送事件或 WebSocket[1]。
局限
同源策略构成最基本的限制:脚本默认只能向与页面同协议、同域名、同端口的地址发起请求并读取响应,跨源访问必须由服务器通过跨源资源共享机制明确授权,否则浏览器会拦截响应[6]。对于不属于简单请求的跨源调用,浏览器还会先发出一次预检请求,服务器未正确应答时实际请求不会发出[7]。
同步模式是另一处明显短板。open() 的第三个参数可指定同步执行,此时脚本会一直等待服务器响应,浏览器单线程的脚本执行随之中断,界面在此期间无法响应操作[2]。因此同步请求不可在 Web Worker 之外使用,页面脚本应尽量避免依赖它[2]。
接口本身以事件回调组织流程,缺少基于 Promise 的组合能力,多请求串联或统一错误处理时写法较为繁琐;Web 超文本应用技术工作小组另行制定的 Fetch API 提供了基于 Promise 的替代方案,被视为功能更强的后继者[6]。此外,跨源响应中的标头并非全部对脚本可见,Set-Cookie 一类标头始终由浏览器自行处理,脚本无法读取[8]。
参见
参考资料
- XMLHttpRequest [引用日期2026-10-29]
- 使用 XMLHttpRequest [引用日期2026-10-29]
- XMLHttpRequest: readyState 属性 [引用日期2026-10-29]
- Ajax (programming) [引用日期2026-10-29]
- epfl.ch 上的网页 [引用日期2026-10-29]
- 网络和通信 [引用日期2026-10-29]
- api. [引用日期2026-10-29]
- XMLHttpRequest [引用日期2026-10-29]