13

How to use async functions with Array.some and every in Javascript - Advanced We...

 4 years ago
source link: https://advancedweb.hu/how-to-use-async-functions-with-array-some-and-every-in-javascript/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

In the first article, we’ve covered how async/await helps with async commands but it offers little help when it comes to asynchronously processing collections. In this post, we’ll look into the some and the every functions that are used for a more efficient reduce when the result is a boolean value.

The some and every functions

These functions get an iteratee function, just like the filter, but they return a single true/false, depending on whether the predicate returned a specific value. In the case of the some, if any of the predicates returned true, the result will be true. For the every function, if any returned false, the result will be false.

const arr = [1, 2, 3];

const someRes = arr.some((i) => {
	return i % 2 === 0;
});

console.log(someRes);
// true

const everyRes = arr.every((i) => {
	return i < 2;
});

console.log(everyRes);
// false

Async some/every

Using an async filter

Considering only the result, these functions can be emulated with an async filter, which is already covered in a previous article how to convert to async.

// sync
const some = (arr, predicate) => arr.filter(predicate).length > 0;
const every = (arr, predicate) => arr.filter(predicate).length === arr.length;

// async
const asyncSome =
	async (arr, predicate) => (await asyncFilter(arr, predicate)).length > 0;
const asyncEvery =
	async (arr, predicate) => (await asyncFilter(arr, predicate)).length === arr.length;

Filter-based async someasyncSomeasyncSomefilteri % 2 === 0filteri % 2 === 0e1e1e2e2e3e3[1, 2, 3]falsetruefalse[2]true

Short-circuiting

But there is an important difference between the built-in some/every functions and the filter-based implementations. When there is an element that returns true for a some, it short-circuits and does not process the remaining elements:

const arr = [1, 2, 3];

const res = arr.some((i) => {
	console.log(`Checking ${i}`);
	return i % 2 === 0;
});

// Checking 1
// Checking 2

console.log(res);
// true

Synchronous somesomesomee1e1e2e2e3e3falsetrueDoes notchecktrue

Similarly, every stops after the first false result:

const arr = [1, 2, 3];

const res = arr.every((i) => {
	console.log(`Checking ${i}`);
	return i < 2;
});

// Checking 1
// Checking 2

console.log(res);
// false

Let’s see how to code an async version that works in a similar way and does the least amount of work!

Shameless plug
We write articles like this regularly. Join our mailing list and let's keep in touch.

Async some

The best solution is to use an async for iteration that returns as soon as it finds a truthy result:

const arr = [1, 2, 3];

const asyncSome = async (arr, predicate) => {
	for (let e of arr) {
		if (await predicate(e)) return true;
	}
	return false;
};
const res = await asyncSome(arr, async (i) => {
	console.log(`Checking ${i}`);
	await sleep(10);
	return i % 2 === 0;
});

// Checking 1
// Checking 2

console.log(res);
// true

For-based async someasyncSomeasyncSomee1e1e2e2e3e3falsetrueDoes notchecktrue

For the first element predicate(e) returns true, it concludes the for-loop.

Async every

The similar structure works for every, it’s just a matter of negating the conditions:

const arr = [1, 2, 3];

const asyncEvery = async (arr, predicate) => {
	for (let e of arr) {
		if (!await predicate(e)) return false;
	}
	return true;
};
const res = await asyncEvery(arr, async (i) => {
	console.log(`Checking ${i}`);
	await sleep(10);
	return i < 2;
});

// Checking 1
// Checking 2

console.log(res);
// false

Whenever there is a false value returned by predicate(e), the function is ended without checking the other elements.

Parallel processing

The short-circuiting implementation processes the elements sequentially, which is efficient in terms of resource usage, but it might result in longer execution.

For example, if the iteratee sends requests via a network, it might take some time to send them one at a time. On the other hand, while it might result in more requests sent, sending all of them at the same time would be faster.

Conclusion

The some and the every functions are easy to approximate with an async filter but to follow the synchronous version faithfully, an async for loop is a better choice.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK