Sunday 12 January 2020

For Await Of

The other day I came across something I had missed regarding for-await-of loops (the ones for traversing Async Iterables), they also work with Synchronous Iterables!. It's explained here:

for-await-of handles synchronous iterables by converting them to asynchronous iterables. Each iterated value is converted to a Promise (or left unchanged if it already is a Promise) via Promise.resolve(). That is, for-await-of works for iterables over Promises and over normal values.

We can see a simple example:

let cities = ["Toulouse", "Lyon", "Xixon"];

async function* asyncCities(){
		for (let city of cities){
			yield await new Promise(res => setTimeout(() => res(city), 700));
		}
}


async function print(items){
	for await (let it of items){
		console.log(it.toUpperCase());
	}
}

(async () => {
	await print(cities);
	console.log("------");
	await print(asyncCities());

})();

This comes in line with the feature that in javascript we can await for a non-promise value (the runtime will convert it into a Promise by calling Promise.resolve [1]).

This fits perfectly in a dynamic language like JavaScript. We can think of an scenario for example where we can receive either an iterable of cached values, or an iterable that has to retrieve those values asynchronously. The same function can receive one or another itarable and iterate it with for-async-of.

In the other language that I know with a similar feature, C# and its Async Streams, things are much more rigid. The await-foreach loop will only work with IAsycnEnumerables. If we try to iterate with it an IAsyncEnumerator we get a compilation error of this sort:

Asynchronous foreach statement cannot operate on variables of type 'List' because 'List' does not contain a public instance definition for 'GetAsyncEnumerator'.

Even if we were allowed to do this, it would not be much useful. IAsyncEnumerable does not inherit from IEnumerable, so the case that I've just mentioned of a same method receiving either an IEnumerable of cached values or an IAsyncEnumerable that retrieves the values asynchronously, does not apply.

No comments:

Post a Comment