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) // "成功!"
  })

静态方法详解

  1. Promise.all:全部成功时返回结果数组,任何一个失败立即reject

    Promise.all([
      fetch('/api/user'),
      fetch('/api/posts')
    ]).then(([user, posts]) => {
      // 两个请求都完成
    })
  2. Promise.race:竞速模式,取最先完成的结果

    Promise.race([
      fetch('/api/main'),
      timeout(5000) // 自定义超时
    ]).then(data => {
      // 先返回的结果
    })
  3. 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实现:

图1

错误处理模式

  1. 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 // 可选择继续抛出
      }
    }
  2. 高阶函数封装

    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)任务队列

任务队列分级

图2

任务类型分类

任务类型示例优先级
微任务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
  • 大量计算分解为多个微任务
  • 使用queueMicrotaskAPI添加微任务

综合实践方案

取消异步操作

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应用的性能和可维护性。根据具体场景选择合适的模式,并注意错误处理和性能优化,可以构建出健壮的异步应用架构。

评论已关闭