JavaScript异步编程:Promise与async/await深度指南
JavaScript异步编程模式深度解析
Promise链式调用与静态方法
Promise核心机制
Promise是ES6引入的异步编程解决方案,通过状态管理(pending/fulfilled/rejected)和链式调用解决了回调地狱问题。
// 基础示例
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('成功'), 1000)
})
promise
.then(value => {
console.log(value) // "成功"
return value + '!'
})
.then(newValue => {
console.log(newValue) // "成功!"
})
静态方法详解
Promise.all:全部成功时返回结果数组,任何一个失败立即reject
Promise.all([ fetch('/api/user'), fetch('/api/posts') ]).then(([user, posts]) => { // 两个请求都完成 })
Promise.race:竞速模式,取最先完成的结果
Promise.race([ fetch('/api/main'), timeout(5000) // 自定义超时 ]).then(data => { // 先返回的结果 })
Promise.allSettled:ES2020新增,不短路,收集所有结果
Promise.allSettled([promise1, promise2]) .then(results => { results.forEach(result => { if (result.status === 'fulfilled') { console.log(result.value) } else { console.error(result.reason) } }) })
实践建议:
- 始终添加
.catch()
处理错误 - 避免在Promise构造函数中执行同步代码
- 使用
Promise.all
优化并行异步操作
async/await原理与错误处理
实现原理
async/await是Generator的语法糖,基于Promise实现:
错误处理模式
try/catch方式:
async function fetchData() { try { const response = await fetch('/api/data') const data = await response.json() return data } catch (error) { console.error('请求失败:', error) throw error // 可选择继续抛出 } }
高阶函数封装:
function withErrorHandling(fn) { return async (...args) => { try { return await fn(...args) } catch (err) { // 统一错误处理逻辑 sendErrorToLog(err) return null } } } const safeFetch = withErrorHandling(fetchData)
性能注意:
- 每个await都会创建新的微任务
非依赖的await应并行执行:
// 低效写法 const user = await getUser() const posts = await getPosts() // 优化写法 const [user, posts] = await Promise.all([ getUser(), getPosts() ])
生成器(Generators)与协程
生成器基础
通过function*
定义,配合yield
实现暂停/恢复:
function* idGenerator() {
let id = 1
while (true) {
yield id++
}
}
const gen = idGenerator()
console.log(gen.next().value) // 1
console.log(gen.next().value) // 2
协程实现
手动执行生成器实现协程调度:
function run(generatorFunc) {
const gen = generatorFunc()
function iterate(iteration) {
if (iteration.done) return iteration.value
const promise = iteration.value
return promise.then(x => iterate(gen.next(x)))
}
return iterate(gen.next())
}
run(function*() {
const result1 = yield Promise.resolve(1)
const result2 = yield Promise.resolve(2)
console.log(result1 + result2) // 3
})
应用场景:
- 复杂异步流程控制
- 按需懒加载
- 无限数据流处理
事件循环(Event Loop)任务队列
任务队列分级
任务类型分类
任务类型 | 示例 | 优先级 |
---|---|---|
微任务 | Promise回调、MutationObserver | 高 |
宏任务 | setTimeout、setInterval、I/O | 低 |
渲染任务 | requestAnimationFrame | 中 |
执行顺序示例:
console.log('脚本开始')
setTimeout(() => console.log('setTimeout'), 0)
Promise.resolve()
.then(() => console.log('Promise 1'))
.then(() => console.log('Promise 2'))
console.log('脚本结束')
/* 输出顺序:
脚本开始
脚本结束
Promise 1
Promise 2
setTimeout
*/
性能优化建议:
- 耗时操作放入Web Worker
- 大量计算分解为多个微任务
- 使用
queueMicrotask
API添加微任务
综合实践方案
取消异步操作
function createCancelablePromise(promise) {
let cancel
const wrappedPromise = new Promise((resolve, reject) => {
cancel = reject
promise.then(resolve, reject)
})
return {
promise: wrappedPromise,
cancel: (reason = 'Cancelled') => cancel(reason)
}
}
const { promise, cancel } = createCancelablePromise(fetch('/api'))
setTimeout(cancel, 5000) // 5秒后取消
进度通知
async function withProgress(promise, onProgress) {
let progress = 0
const interval = setInterval(() => {
progress = Math.min(progress + 10, 90)
onProgress(progress)
}, 300)
try {
const result = await promise
onProgress(100)
return result
} finally {
clearInterval(interval)
}
}
withProgress(fetchLargeFile(), p => {
console.log(`下载进度: ${p}%`)
})
掌握这些异步编程模式,能够显著提升JavaScript应用的性能和可维护性。根据具体场景选择合适的模式,并注意错误处理和性能优化,可以构建出健壮的异步应用架构。
评论已关闭