与Typescript / ES7中的async / await有限的并行性 [英] Limited parallelism with async/await in Typescript/ES7
问题描述
我一直在尝试使用Typescript,但我现在对如何有效地使用async / await感到困惑。
I've been experimenting a bit with Typescript, but I'm now a bit stuck on how to use async/await effectively.
我正在插入一个一堆记录到数据库中,我需要获取每个插入返回的ID列表。以下简化示例一般都有效,但它并不像我想的那样优雅,而且完全是顺序的。
I'm inserting a bunch of records into a database, and I need to get the list of IDs that are returned by each insert. The following simplified example works in general, but it is not quite as elegant as I'd like and it is completely sequential.
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
列表,但我可以让这个工作。
I tried to use map
to avoid creating the ids
list manually, but I could get this to work.
我还想拥有的是有限的并行度。所以我的异步调用应该并行发生,直到某个限制,例如我只想要有10个开放请求,但不是更多。
What I'd also like to have is a limited amount of parallelism. So my asynchronous calls should happen in parallel up to a certain limit, e.g. I'd only ever like to have 10 open requests, but not more.
在Typescript中使用async / await实现这种有限并行性是否有一种相当优雅的方式还是Javascript ES7?或者我是否试图让这个功能做一些不适合的事情?
Is there a reasonably elegant way of achieving this kind of limited parallelism with async/await in Typescript or Javascript ES7? Or am I trying to get this feature to do something it was not intended for?
PS:我知道有数据库的批量插入方法,这个例子是有点人为,因为我可以使用它来解决这个特定的问题。但它让我想知道我没有预定义的批量方法可用的一般情况,例如:网络请求
推荐答案
Promise.all
将允许等待所有请求停止完成,而不阻止他们的创建。
Promise.all
will allow you to wait for all requests to stop finishing, without blocking their creation.
然而, 听起来有时候会阻止。具体来说,听起来你想在任何给定时间节流飞行中的请求数量。这是我掀起的东西(但尚未经过全面测试!)
However, it does sound like you want to block sometimes. Specifically, it sounded like you wanted to throttle the number of requests in flight at any given time. Here's something I whipped up (but haven't fully tested!)
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
是一组当前正在进行的操作。
Above, inFlight
is a set of operations that are currently taking place.
结果
是一个数组包裹 承诺
s。每个包装的promise都基本上添加或删除了 inFlight
操作集中的操作。如果有太多的飞行操作,那么这将使用 Promise.race
来完成任何一个正在进行的操作。
The result
is an array of wrapped Promise
s. Each of those wrapped promises basically adds or removes operations from the set of inFlight
operations. If there are too many in-flight operations, then this uses Promise.race
for any one of the in-flight operations to complete.
希望有所帮助。
这篇关于与Typescript / ES7中的async / await有限的并行性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!