javascript - 当嵌套的 promise 实际上有数千个时,这是一个正确的异步/等待实现吗?

标签 javascript node.js asynchronous async-await promise

关于:https://github.com/gvasquez95/binance-trader/issues/8

我担心实际的“内部”等待(在 getPriceChange 的每次调用中)不会阻止异步调用此方法在外部循环中进行的大约 1.5k 次调用 (getPriceChanges)。如果它是阻塞的,那么循环将是串行处理。

从性能 Angular 和时间来看,我想说它按预期工作,因为它只需要几秒钟就可以完成整个过程,但是,如果可能的话,我想要一个假设的编程 ACK。

为那些不想进入 GitHub 并且希望代码更可见的人屏蔽代码:

外循环:

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 }
}

更新: 在配置有 624 MB RAM 的 Node.js 14.x AWS Lambda 环境中,函数执行大约需要 30 秒,从成本 Angular 来看,DynamoDB 查询(ReadRequests)成本和 Lambda 执行都是实际 DynamoDB Batch 的 1/50放置操作(WriteRequest),因此优化查询应该是一个需要的目标。

最佳答案

您的循环是正确的异步循环。而且您似乎担心同时有多少查询会在飞行中。在您的情况下,您打算进行许多并发查询,并且您已经这样做了。

解释

在订购 10 个比萨饼的简单示例中,请考虑以下数组:

同时

这是一组披萨订单。我们可以等待所有 10 个订单以获得 10 个比萨饼的数组。假设当晚至少有 10 名送货员在工作,那么您很有可能会在 30 分钟内拿到所有的比萨饼。

for (let i = 0; i < 10; ++i) {
   orders.push(orderPizza());
}
pizzas = await Promise.all(orders);

依次

这是一系列披萨。每个订单在发出时都在等待。如果每个披萨在 30 分钟内送达或免费,这可能会导致等待最后一个披萨的时间大约为 5 小时(10 * ~30 分钟),因为下一个披萨要等到前一个披萨到达时才会订购。 (在这种情况下不需要最终的 Promise.all,因为在继续循环之前每个 promise 都已经解决。)

for (let i = 0; i < 10; ++i) {
   pizzas.push(await orderPizza());
}

关于javascript - 当嵌套的 promise 实际上有数千个时,这是一个正确的异步/等待实现吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69350739/

相关文章:

javascript - 使用请求并让回调在函数内工作的异步调用

javascript - Google 文档从文本区域发布表格

javascript - 从 JavaScript 中的动态表输入文本框创建动态对象

javascript - 有人可以解密这个 javascript 吗?

javascript - Route.delete() 需要一个回调函数,但得到一个 [object Undefined]

Javascript:变量值在回调中使用之前发生变化

c# - 对 .NET 4 异步的困惑

javascript - jQuery 保持其他框未编辑状态

javascript - 如何在 azure 上部署和运行 Passport Express Node

node.js - 如何处理加载大集合的所有记录并监听 mongodb atlas 上的新数据?