关于: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/