JavaScript 提供了多种与服务器通信的方式,从传统的 XMLHttpRequest 到现代的 Fetch API。
// 创建 XMLHttpRequest 实例
const xhr = new XMLHttpRequest()
// 配置请求
xhr.open('GET', 'https://api.example.com/data', true)
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.setRequestHeader('Authorization', 'Bearer token123')
// 设置响应类型
xhr.responseType = 'json' // 'text', 'json', 'blob', 'arraybuffer', 'document'
// 发送请求
xhr.send()
// 处理响应
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log('Response:', xhr.response)
} else {
console.error('Error:', xhr.status, xhr.statusText)
}
}
}
// 监听事件
xhr.onload = function() {
console.log('Request completed successfully')
}
xhr.onerror = function() {
console.error('Network error occurred')
}
xhr.onprogress = function(event) {
if (event.lengthComputable) {
const percent = (event.loaded / event.total) * 100
console.log(`Progress: ${percent}%`)
}
}// GET 请求
function sendGetRequest(url, params = {}) {
const queryString = new URLSearchParams(params).toString()
const fullUrl = queryString ? `${url}?${queryString}` : url
const xhr = new XMLHttpRequest()
xhr.open('GET', fullUrl)
xhr.responseType = 'json'
xhr.onload = function() {
if (xhr.status === 200) {
console.log('GET Response:', xhr.response)
}
}
xhr.send()
}
// POST 请求
function sendPostRequest(url, data) {
const xhr = new XMLHttpRequest()
xhr.open('POST', url)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.onload = function() {
if (xhr.status === 200 || xhr.status === 201) {
console.log('POST Response:', xhr.response)
}
}
xhr.send(JSON.stringify(data))
}
// 文件上传
function uploadFile(url, file) {
const formData = new FormData()
formData.append('file', file)
const xhr = new XMLHttpRequest()
xhr.open('POST', url)
xhr.upload.onprogress = function(event) {
const percent = (event.loaded / event.total) * 100
console.log(`Upload progress: ${percent}%`)
}
xhr.onload = function() {
if (xhr.status === 200) {
console.log('File uploaded successfully')
}
}
xhr.send(formData)
}const xhr = new XMLHttpRequest()
// 设置超时
xhr.timeout = 5000 // 5秒超时
xhr.ontimeout = function() {
console.error('Request timed out')
}
// 取消请求
const cancelButton = document.getElementById('cancelBtn')
cancelButton.addEventListener('click', () => {
xhr.abort()
console.log('Request cancelled')
})// GET 请求
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
return response.json()
})
.then(data => console.log('Data:', data))
.catch(error => console.error('Error:', error))
// POST 请求
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123'
},
body: JSON.stringify({
name: 'John Doe',
email: 'john@example.com'
})
})
.then(response => response.json())
.then(data => console.log('Created user:', data))const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${token}`,
'X-Custom-Header': 'custom-value'
},
body: JSON.stringify(data),
mode: 'cors', // 'cors', 'no-cors', 'same-origin'
credentials: 'include', // 'omit', 'same-origin', 'include'
cache: 'no-cache', // 'default', 'no-cache', 'reload', 'force-cache', 'only-if-cached'
redirect: 'follow', // 'follow', 'error', 'manual'
referrer: 'client', // 'no-referrer', 'client', 'no-referrer-when-downgrade'
referrerPolicy: 'no-referrer-when-downgrade',
integrity: '', // 子资源完整性检查
keepalive: false, // 请求在页面卸载后继续
signal: null // AbortSignal 用于取消请求
}
fetch(url, requestOptions)// JSON 响应
fetch('/api/data')
.then(response => response.json())
.then(data => console.log(data))
// 文本响应
fetch('/api/text')
.then(response => response.text())
.then(text => console.log(text))
// Blob 响应(文件下载)
fetch('/api/file')
.then(response => response.blob())
.then(blob => {
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'filename.ext'
a.click()
URL.revokeObjectURL(url)
})
// ArrayBuffer 响应
fetch('/api/binary')
.then(response => response.arrayBuffer())
.then(buffer => {
// 处理二进制数据
const view = new Uint8Array(buffer)
console.log(view)
})
// FormData 响应
fetch('/api/form')
.then(response => response.formData())
.then(formData => {
for (let [key, value] of formData) {
console.log(key, value)
}
})// 错误处理
fetch('/api/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
return response.json()
})
.then(data => console.log('Success:', data))
.catch(error => {
if (error.name === 'TypeError') {
console.error('Network error:', error.message)
} else {
console.error('Other error:', error.message)
}
})
// 超时控制
function fetchWithTimeout(url, options = {}, timeout = 5000) {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeout)
return fetch(url, {
...options,
signal: controller.signal
})
.finally(() => clearTimeout(timeoutId))
}
// 使用 AbortController 取消请求
const controller = new AbortController()
const cancelBtn = document.getElementById('cancelBtn')
cancelBtn.addEventListener('click', () => {
controller.abort()
})
fetch('/api/long-running', {
signal: controller.signal
})
.catch(error => {
if (error.name === 'AbortError') {
console.log('Request was cancelled')
}
})// 发送分析数据(在页面卸载时发送)
function sendAnalytics(data) {
const blob = new Blob([JSON.stringify(data)], {
type: 'application/json'
})
navigator.sendBeacon('/api/analytics', blob)
}
// 页面卸载时发送数据
window.addEventListener('unload', () => {
sendAnalytics({
url: location.href,
timestamp: Date.now(),
userAgent: navigator.userAgent
})
})
// 或者在页面隐藏时发送
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
sendAnalytics({
action: 'page_hidden',
timestamp: Date.now()
})
}
})// 创建 WebSocket 连接
const ws = new WebSocket('ws://localhost:8080')
// 连接事件
ws.onopen = function(event) {
console.log('WebSocket connected')
ws.send('Hello Server!')
}
// 消息事件
ws.onmessage = function(event) {
console.log('Received:', event.data)
const data = JSON.parse(event.data)
handleMessage(data)
}
// 错误事件
ws.onerror = function(event) {
console.error('WebSocket error:', event)
}
// 关闭事件
ws.onclose = function(event) {
console.log('WebSocket closed:', event.code, event.reason)
}
// 发送消息
function sendMessage(type, payload) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
type,
payload,
timestamp: Date.now()
}))
}
}
// 关闭连接
ws.close(1000, 'Normal closure')class WebSocketManager {
constructor(url, options = {}) {
this.url = url
this.options = {
heartbeatInterval: 30000, // 30秒
reconnectInterval: 5000, // 5秒
maxReconnectAttempts: 5,
...options
}
this.ws = null
this.heartbeatTimer = null
this.reconnectTimer = null
this.reconnectAttempts = 0
this.connect()
}
connect() {
this.ws = new WebSocket(this.url)
this.ws.onopen = () => {
console.log('WebSocket connected')
this.reconnectAttempts = 0
this.startHeartbeat()
this.options.onOpen && this.options.onOpen()
}
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data)
if (data.type === 'pong') {
console.log('Heartbeat received')
} else {
this.options.onMessage && this.options.onMessage(data)
}
}
this.ws.onclose = (event) => {
console.log('WebSocket closed:', event.code, event.reason)
this.stopHeartbeat()
this.options.onClose && this.options.onClose(event)
if (!event.wasClean && this.reconnectAttempts < this.options.maxReconnectAttempts) {
this.scheduleReconnect()
}
}
this.ws.onerror = (error) => {
console.error('WebSocket error:', error)
this.options.onError && this.options.onError(error)
}
}
startHeartbeat() {
this.heartbeatTimer = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type: 'ping' }))
}
}, this.options.heartbeatInterval)
}
stopHeartbeat() {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer)
this.heartbeatTimer = null
}
}
scheduleReconnect() {
this.reconnectAttempts++
console.log(`Reconnecting in ${this.options.reconnectInterval}ms (attempt ${this.reconnectAttempts})`)
this.reconnectTimer = setTimeout(() => {
this.connect()
}, this.options.reconnectInterval)
}
send(data) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data))
}
}
close() {
this.stopHeartbeat()
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer)
}
if (this.ws) {
this.ws.close()
}
}
}
// 使用示例
const wsManager = new WebSocketManager('ws://localhost:8080', {
onOpen: () => console.log('Connected!'),
onMessage: (data) => console.log('Message:', data),
onClose: () => console.log('Disconnected!'),
onError: (error) => console.error('Error:', error)
})
// 发送消息
wsManager.send({ type: 'chat', message: 'Hello!' })
// 清理
window.addEventListener('beforeunload', () => {
wsManager.close()
})网络请求是现代 Web 应用的核心功能:
选择合适的网络技术可以显著提升应用性能和用户体验。