You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套数千个Promise场景下的async/await实现是否正确?

核心结论

你担心的「内层getPriceChange的await会导致外层循环串行执行」的假设不成立,当前代码的所有getPriceChange调用本身是并行触发的。

原理说明

外层getPriceChanges的循环逻辑里,只是直接调用getPriceChange并将返回的Promise实例推入changes数组,全程没有在循环体内使用await,循环不会等待任意一个getPriceChange的异步逻辑执行完成就会继续处理下一个ticker,1500次异步请求会在极短时间内全部触发,之后才会通过await Promise.all(changes)统一等待所有请求返回结果,所以不存在串行执行的问题。

当前Lambda 30秒耗时的原因及优化方案

当前执行耗时较长的核心原因是1500次独立的DynamoDB单Key查询带来的大量网络IO开销和请求排队开销,可通过以下方案优化:

  • 改用DynamoDB的BatchGetItem接口批量查询数据,单次批量请求最多支持同时查询100条数据,1500次查询只需15次请求即可完成,可将查询耗时降低80%以上,同时进一步降低读请求成本。
  • 若受查询逻辑限制无法使用批量查询,可增加并发数控制,限制同时发起的DynamoDB请求数在50~100区间,避免一次性发起过多请求触发DynamoDB读吞吐量限流导致的重试耗时。
  • 对重复查询的热点数据增加缓存层,可使用Lambda内存级缓存或ElastiCache缓存高频查询的价格数据,避免重复查询DynamoDB。

外层getPriceChanges代码

async function getPriceChanges (since, breakpoint) {
  const changes = []
  for (const [i, ticker] of tickers.entries()) {
    if (!ticker.includes('BIDR') && !ticker.includes('BIFI')) {
      changes.push(getPriceChange(ticker, since, breakpoint))
    }
  }
  const res = await Promise.all(changes)
  let symbol
  let maxChange = 0
  let slope = 0
  for (const ticker of res) {
    if (ticker.percentChange > maxChange && ticker.slope > Math.pow(10, -1 * NUM_DECIMALS)) {
      maxChange = ticker.percentChange
      symbol = ticker.symbol
      slope = ticker.slope
    }
  }
  return { symbol, maxChange: Math.round(100 * maxChange) / 100, slope: round(slope, NUM_DECIMALS) }
}

内层getPriceChange代码

async function getPriceChange (symbol, since, breakpoint) {
  const params = {
    TableName: DYNAMODB_TABLE,
    ProjectionExpression: '#timestamp, price',
    KeyConditionExpression: 'symbol = :symbol and #timestamp > :timestamp',
    ExpressionAttributeNames: {
      '#timestamp': 'timestamp'
    },
    ExpressionAttributeValues: {
      ':symbol': symbol,
      ':timestamp': since
    }
  }
  const res = await documentClient.query(params).promise()
  const prev = []
  const recent = []
  const trendData = []
  for (const data of res.Items) {
    if (data.timestamp < breakpoint) {
      prev.push(data.price)
    } else {
      trendData.push({ x: trendData.length, y: data.price })
      recent.push(data.price)
    }
  }
  let sumPrev = 0
  let sumRecent = 0
  for (const price of prev) { sumPrev += price }
  for (const price of recent) { sumRecent += price }
  const avgPrev = sumPrev / prev.length
  const avgRecent = sumRecent / recent.length
  const trend = createTrend(trendData, 'x', 'y')
  return { symbol, percentChange: (100 * (avgRecent - avgPrev)) / avgRecent, slope: trend.slope }
}

内容的提问来源于stack exchange,提问作者gvasquez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:48:00