Appearance
异步/高并发方案
概述
异步编程和高并发处理是现代前端开发的核心技能,涉及事件循环、Promise、async/await 等关键技术。
异步编程基础
1. 回调函数
javascript
function fetchData(callback) {
setTimeout(() => {
callback(null, 'data')
}, 1000)
}2. Promise
javascript
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('data')
}, 1000)
})
}
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error))3. async/await
javascript
async function fetchData() {
try {
const data = await fetch('/api/data')
return data.json()
} catch (error) {
console.error(error)
}
}并发控制
1. Promise.all()
并行执行多个 Promise,等待所有完成:
javascript
const results = await Promise.all([
fetch('/api/1'),
fetch('/api/2'),
fetch('/api/3')
])2. Promise.race()
返回最先完成的 Promise:
javascript
const result = await Promise.race([
fetch('/api/fast'),
timeout(5000)
])3. Promise.allSettled()
等待所有 Promise 完成(无论成功或失败):
javascript
const results = await Promise.allSettled([
fetch('/api/1'),
fetch('/api/2')
])4. 并发限制
javascript
class ConcurrencyQueue {
constructor(limit) {
this.limit = limit
this.queue = []
this.active = 0
}
async run(task) {
if (this.active >= this.limit) {
await new Promise(resolve => this.queue.push(resolve))
}
this.active++
try {
return await task()
} finally {
this.active--
const next = this.queue.shift()
if (next) next()
}
}
}高并发场景
1. 批量请求处理
javascript
async function batchRequests(urls, batchSize = 5) {
const results = []
for (let i = 0; i < urls.length; i += batchSize) {
const batch = urls.slice(i, i + batchSize)
const batchResults = await Promise.all(
batch.map(url => fetch(url))
)
results.push(...batchResults)
}
return results
}2. 请求取消
javascript
const controller = new AbortController()
fetch('/api/data', {
signal: controller.signal
})
// 取消请求
controller.abort()3. 请求重试
javascript
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url)
} catch (error) {
if (i === retries - 1) throw error
await new Promise(r => setTimeout(r, 1000 * i))
}
}
}性能优化
1. 防抖和节流
javascript
// 防抖
function debounce(fn, delay) {
let timer
return function(...args) {
clearTimeout(timer)
timer = setTimeout(() => fn.apply(this, args), delay)
}
}
// 节流
function throttle(fn, delay) {
let last = 0
return function(...args) {
const now = Date.now()
if (now - last >= delay) {
last = now
fn.apply(this, args)
}
}
}2. 虚拟列表
javascript
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0)
const startIndex = Math.floor(scrollTop / itemHeight)
const endIndex = Math.min(
startIndex + Math.ceil(containerHeight / itemHeight),
items.length
)
return (
<div onScroll={e => setScrollTop(e.target.scrollTop)}>
{items.slice(startIndex, endIndex).map(item => (
<div key={item.id}>{item.content}</div>
))}
</div>
)
}最佳实践
1. 错误处理
- 使用 try-catch 捕获异步错误
- 实现全局错误处理
- 记录错误日志
2. 超时控制
javascript
function timeout(promise, ms) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
)
])
}3. 资源清理
- 取消未完成的请求
- 清理定时器
- 移除事件监听器
常见问题
如何处理并发竞态问题?
- 使用请求标识符
- 取消过期的请求
- 使用最新结果
如何优化大量并发请求?
- 实现请求队列
- 控制并发数量
- 使用缓存策略