-
Notifications
You must be signed in to change notification settings - Fork 34
Open
Description
I'm trying to limit uploads to 10 simultaneously, and I'm doing it like this:
const uploadSema = new Sema(10)
for (const upload of uploads) {
await uploadSema.acquire()
uploadOne(upload).finally(() => uploadSema.release())
}
await uploadSema.drain()It's reasonably nice, but I was wondering if there wasn't a way to make this nicer.
I moved the logic to this helper function
export const queuedWork = async (items, fn, workers = 10) => {
const sema = new Sema(workers)
let threw = null
for (const item of items) {
if (threw) break
await sema.acquire()
// eslint-disable-next-line promise/catch-or-return
Promise.resolve(fn(item))
.catch(err => {
threw = err
})
.finally(() => sema.release())
}
await sema.drain()
if (threw) throw threw
}Is this a good way of going about it? Is there maybe a more elegant way?
(wrote these tests too)
test('queuedWork async', async () => {
const out = []
await queuedWork([1, 5, 7, 89, 2], async n => out.push(n), 2)
expect(out).toEqual([1, 5, 7, 89, 2])
})
test('queuedWork sync', async () => {
const out = []
await queuedWork([1, 5, 7, 89, 2], n => out.push(n), 2)
expect(out).toEqual([1, 5, 7, 89, 2])
})
test('queuedWork throws', async () => {
const out = []
await expect(
queuedWork(
[1, 2, 3, 4, 5],
async n => {
if (n === 2) throw new Error('meep')
else out.push(n)
},
2
)
).rejects.toThrow('meep')
expect(out).toEqual([1, 3])
})
test('queuedWork throws sync', async () => {
const out = []
await expect(
queuedWork(
[1, 2, 3, 4, 5],
n => {
if (n === 2) throw new Error('meep')
else out.push(n)
},
2
)
).rejects.toThrow('meep')
expect(out).toEqual([1])
})Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels