跳到主要内容

网络 API

XMLHttpRequest 和 Fetch API 的区别 ?

答案
维度XMLHttpRequest (XHR)Fetch API
API风格基于回调函数,事件驱动基于Promise,链式调用
语法简洁性语法繁琐,需多步配置语法简洁,易于维护
请求/响应处理需手动解析JSON、处理状态json()等方法自动解析
请求头设置setRequestHeader方法Headers对象,配置灵活
请求体字符串、FormData等支持FormData、Blob、URLSearchParams等
取消请求通过abort()方法支持AbortController/AbortSignal
进度事件支持upload/download进度事件仅部分支持,需额外处理
跨域支持CORS,配置复杂支持CORS,配置直观
错误处理需判断readyState/status仅网络错误/中止抛异常,状态码需手动判断
文件上传/下载支持支持
浏览器兼容性兼容性好,老浏览器支持新标准,低版本需polyfill
自定义请求支持支持Request对象,功能丰富

补充说明

  • XHR 适合兼容性要求高、需进度事件的场景,但API繁琐。
  • Fetch API 语法现代,Promise链式处理更优雅,推荐新项目优先使用。
  • Fetch 支持通过 AbortController 取消请求,XHR 通过 abort() 方法实现。
  • 错误处理上,Fetch 只对网络错误抛异常,状态码错误需手动判断。
// XHR 示例
const xhr = new XMLHttpRequest()
xhr.open('GET', '/api/data')
xhr.onload = () => { if (xhr.status === 200) console.log(xhr.responseText) }
xhr.send()

// Fetch 示例
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err))
提示

推荐新项目优先使用 Fetch API,语法更现代,易于维护。需兼容老浏览器时可用 XHR 或引入 polyfill。

延伸阅读

Long-Polling、Websockets 和 Server-Sent Event 之间有什么区别?

答案
维度Long-PollingWebSocketServer-Sent Event (SSE)
连接方式HTTP短连接TCP长连接HTTP长连接
数据流向单向(服务端→客户端)双向(全双工)单向(服务端→客户端)
实时性较好极佳
兼容性广泛现代浏览器较好(IE不兼容)
典型场景消息推送、IM实时协作、游戏、IM实时通知、数据流
特点/限制每次响应后需重新请求,资源消耗大需服务端支持,初始握手复杂仅支持文本,无法双向通信

补充说明

  • Long-Polling 通过不断发起 HTTP 请求模拟实时推送,兼容性好但效率低。
  • WebSocket 支持双向通信,适合高实时性场景,但需服务端专门支持。
  • SSE 适合服务端单向推送,API简单,自动重连,但不支持 IE,且仅支持文本数据。
提示

如需双向实时通信优先选 WebSocket,单向推送可用 SSE,兼容性优先时可选 Long-Polling。

延伸阅读

说下 navigator.sendBeacon

答案
特性sendBeaconfetch(keepalive)
用途异步发送小量数据,常用于埋点、统计可发送更复杂请求,支持 keepalive 保证卸载时发送
触发时机页面卸载、关闭等页面卸载、关闭等
数据类型文本、Blob、FormData 等任意 body 类型
数据量限制较小(通常几十 KB)约 64KB(各浏览器略有差异)
返回值布尔值,表示是否入队Promise,无法保证一定送达
阻塞卸载
兼容性现代浏览器广泛支持现代浏览器支持,部分低版本不支持 keepalive

核心概念与原理

  • navigator.sendBeacon(url, data) 设计用于在页面卸载时异步、可靠地发送小量数据,不阻塞页面关闭。底层通过浏览器任务队列保证请求尽量送达,适合统计、日志等场景。
  • fetchkeepalive: true 选项也可用于类似场景,但有更严格的数据量限制,且部分老浏览器不支持。

常见误区

  • 误以为 sendBeacon 能保证 100% 送达,实际上网络异常等仍可能丢失。
  • sendBeacon 只适合小数据量,超出限制可能被丢弃。
  • fetch keepalive 不是所有浏览器都支持,且请求体过大时会失败。

代码示例

// 推荐:页面卸载时发送埋点
window.addEventListener('unload', () => {
const data = { event: 'leave', time: Date.now() }
navigator.sendBeacon('/api/track', JSON.stringify(data))
})

// 备选方案:fetch + keepalive
window.addEventListener('beforeunload', () => {
const data = { event: 'leave', time: Date.now() }
fetch('/api/track', {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
keepalive: true
})
})
提示

统计/埋点等需保证卸载时送达的小数据,优先用 sendBeacon。需发送大数据或自定义请求时可用 fetch+keepalive,但注意兼容性和体积限制。

延伸阅读

SSE

一个网页获取新的数据通常需要发送一个请求到服务器,也就是向服务器请求的页面。使用 server-sent 事件,服务器可以在任何时刻向我们的 Web 页面推送数据和信息。这些被推送进来的信息可以在这个页面上作为 Events + data 的形式来处理。

从服务器接受事件

服务器发送事件 API 也就是 EventSource 接口,在你创建一个新的 EventSource 对象的同时,你可以指定一个接受事件的 URI。例如:

const evtSource = new EventSource('ssedemo.php')

如果发送事件的脚本不同源,应该创建一个新的包含 URL 和 options 参数的EventSource对象。例如,假设客户端脚本在 example.com 上:

const evtSource = new EventSource('//api.example.com/ssedemo.php', { withCredentials: true })

一旦你成功初始化了一个事件源,就可以对 message 事件添加一个处理函数开始监听从服务器发出的消息了:

evtSource.onmessage = function (event) {
const newElement = document.createElement('li')
const eventList = document.getElementById('list')

newElement.innerHTML = 'message: ' + event.data
eventList.appendChild(newElement)
}

你也可以使用addEventListener()方法来监听其他类型的事件:

evtSource.addEventListener('ping', function (event) {
const newElement = document.createElement('li')
const time = JSON.parse(event.data).time
newElement.innerHTML = 'ping at ' + time
eventList.appendChild(newElement)
})

警告: 当不通过 HTTP / 2 使用时,SSE(server-sent events)会受到最大连接数的限制,这在打开各种选项卡时特别麻烦,因为该限制是针对每个浏览器的,并且被设置为一个非常低的数字(6)。该问题在 Chrome 和 Firefox中被标记为“无法解决”。此限制是针对每个浏览器 + 域的,因此这意味着您可以跨所有选项卡打开 6 个 SSE 连接到 <www.example1.com,并打开> 6 个 SSE 连接到 www.example2.com。(来自 Stackoverflow)1。使用 HTTP / 2 时,HTTP 同一时间内的最大连接数由服务器和客户端之间协商(默认为 100)。

SSE 的 API

属性(只读)

名称作用类型备注
readyState当前状态Number0 — connecting1 — open2 — closed
url当前连接的地址String
withCredentials是否开启凭据收集Boolean

方法

名称作用返回值
close客户端主动关闭连接-

事件

名称作用返回值
onclose连接关闭触发event
onopen连接开启触发event
onmessage服务端消息推动消息触发event

服务端 API

名称作用类型备注
data传输的文本String(默认). 可以传输JSON可以多行累加
event事件名称String可自定义
id当前推送 idString作为消息的标识
retry超时重试时间Number客户端在感知 server 连接异常后。会通过 retry 设定时间进行重新连接

补充: SSE 与 WS 有什么区别?

方式协议交互通道内容编码重连事件类型总结
SSEHTTP服务端单向推送默认文本默认支持断线重连支持自定义消息类型轻量级
WebSocketWS(基于 TCP 传输层的应用层协议,RFC6455 [1] 对于它的定义标准)双向推送默认二进制手动实现NO扩展性、功能性强大

参考文档

48%