我一直在尝试使用 Typescript,但我现在对如何有效使用 async/await 有点困惑。
我正在向数据库中插入一堆记录,我需要获取每次插入返回的 ID 列表。下面的简化示例一般有效,但它并不像我想要的那样优雅,而且它完全是顺序的。
async function generatePersons() {
const names = generateNames(firstNames, lastNames);
let ids = []
for (let name of names) {
const id = await db("persons").insert({
first_name: name.firstName,
last_name: name.lastName,
}).returning('id');
ids.push(id[0])
}
return ids
}
我尝试使用 map
来避免手动创建 ids
列表,但我可以让它工作。
我还想拥有有限数量的并行性。所以我的异步调用应该在一定限度内并行发生,例如我只希望有 10 个开放请求,但不会更多。
在 Typescript 或 Javascript ES7 中,是否有一种相当优雅的方法可以通过 async/await 实现这种有限的并行性?还是我试图让这个功能做一些它不打算做的事情?
PS:我知道有针对数据库的批量插入方法,这个例子有点人为,因为我可以使用它们来解决这个特定问题。但这让我想知道一般情况下我没有可用的预定义批量方法,例如有网络请求
最佳答案
Psst, there's a package that does this for you on npm called p-map
Promise.all
将允许您等待所有请求停止完成,而不会阻止它们的创建。
但是,它确实听起来像您有时想要阻止。具体来说,听起来您想在任何给定时间限制飞行中的请求数量。这是我突然想到的东西(但还没有完全测试!)
async function asyncThrottledMap<T, U>(maxCount: number, array: T[], f: (x: T) => Promise<U>) {
let inFlight = new Set<Promise<U>>();
const result: Promise<U>[] = [];
// Sequentially add a Promise for each operation.
for (let elem of array) {
// Wait for any one of the promises to complete if there are too many running.
if (inFlight.size >= maxCount) {
await Promise.race(inFlight);
}
// This is the Promise that the user originally passed us back.
const origPromise = f(elem);
// This is a Promise that adds/removes from the set of in-flight promises.
const handledPromise = wrap(origPromise);
result.push(handledPromise);
}
return Promise.all(result);
async function wrap(p: Promise<U>) {
inFlight.add(p);
const result = await p;
inFlight.delete(p);
return result;
}
}
上面,inFlight
是一组当前正在进行的操作。
result
是一个由包装 Promise
组成的数组。这些包装的 promise 中的每一个基本上都在 inFlight
操作集中添加或删除操作。如果进行中的操作太多,那么这将使用 Promise.race
来完成任何一个进行中的操作。
希望对您有所帮助。
关于javascript - Typescript/ES7 中异步/等待的有限并行性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39195441/