question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Some nice way of async iterating?

See original GitHub issue

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

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
wmertenscommented, Sep 19, 2019

@cardin but in both cases it does use O(n) memory, and at some point that becomes too much.

Processing an array with “workers” uses only O(nWorkers) memory.

V8 is pretty efficient, but if small changes (amount of code is similar) can use less memory, that’s a good thing, right? Less memory trashing => less GC => faster, even apart from host constraints

0reactions
OlliVcommented, Sep 19, 2019

@wmertens oh right. I have seen that happening (OOM). I have used array-split for splitting a long array and processing it in chunks.

Maybe I could add it to the examples.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Async iteration and generators - The Modern JavaScript Tutorial
Asynchronous iteration allow us to iterate over data that comes asynchronously, on-demand. Like, for instance, when we download something ...
Read more >
Iterating Asynchronously: How to use async & await ... - Medium
This method is used when you have a bunch of tasks that you want to await all at once. We then await the...
Read more >
for await...of - JavaScript - MDN Web Docs
The for await...of statement creates a loop iterating over async iterable objects as well as sync iterables. This statement can only be used ......
Read more >
How to use async/await inside loops in JavaScript
Iterating through items and dealing with asynchronous logic (i.e. API calls) are probably two of the most common tasks we have to perform...
Read more >
what's the best method to handle async iterators and await?
If you want to run the operations sequentially, then use a regular for loop instead of .forEach() since for will wait for your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found