Skip to content

Instantly share code, notes, and snippets.

@XoseLluis
Last active February 16, 2020 15:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save XoseLluis/72e86f2956dfd7a66530657672576a37 to your computer and use it in GitHub Desktop.
Save XoseLluis/72e86f2956dfd7a66530657672576a37 to your computer and use it in GitHub Desktop.
POC Methods for Async Iterables. A continuation to my previous (lazyIterable) gist: https://gist.github.com/XoseLluis/69ab06d98dad132a36ee1c580e08df1f
const printDebug = (msg) => console.log(msg);
class AsyncExtendedIterable{
constructor(iterable){
this.iterable = iterable;
}
async *[Symbol.asyncIterator](){
for await (let it of this.iterable){
yield it;
}
}
map(fn){
//I need to use the old "self" trick, cause we can not declare a generator with an arrow function
//so as we are using a normal function, "this" is dynamic, so we have to trap it via "self"
let self = this;
async function* _map(fn){
for await (let it of self.iterable){
//we can await in a non Promise value, so if we do "yield await" rather than just "yield", we are contemplating both a sync and an async fn mapping funtion (iteratee)
//yield fn(it);
yield await fn(it);
}
};
let newIterable = _map(fn);
return new AsyncExtendedIterable(newIterable);
}
filter(fn){
let self = this;
async function* _filter(fn){
//printDebug("_filter");
for await (let it of self.iterable){
//add an "await" so that it also works with async iteratees
//if (fn(it))
if (await fn(it))
yield it;
}
};
let newIterable = _filter(fn);
return new AsyncExtendedIterable(newIterable);
}
}
async function* citiesAsyncGeneratorFn(){
let cities = ["Xixon", "Toulouse", "Lisbon", "Tours"];
for (city of cities){
let cityPr = new Promise(res => setTimeout(() => res(city), 1000));
yield await cityPr;
}
}
//--------------------------------------
(async () =>{
let citiesAsync = citiesAsyncGeneratorFn(); //it's an async generator function, we don't use await when calling it, though it has the "async" identifier, it does not return a Promise of an AsyncGenerator, it returns an AsyncGenerator
console.log("- " + Reflect.getPrototypeOf(citiesAsync)); //- [object AsyncGenerator]
let extendedIterable = new AsyncExtendedIterable(citiesAsync);
let result = extendedIterable.map(it => it.toUpperCase())
.filter(it => it.startsWith("T"));
console.log("before iterating async Iterable");
for await (let it of result){
console.log(it);
}
console.log("-------------------");
//now let's use it with an asyncITerable and with an async map function
//create a new iterator, the previous one has already reached its end
citiesAsync = citiesAsyncGeneratorFn();
extendedIterable = new AsyncExtendedIterable(citiesAsync);
result = extendedIterable.map(it => {
console.log("starting async toUpper");
return new Promise(res => setTimeout(() => res(it.toUpperCase()), 1000));
})
.filter(it => it.startsWith("T"));
console.log("before iterating async Iterable and applying an map function");
for await (let it of result){
console.log(it);
}
console.log("-------------------");
//we can use it also with a synchronous iterable
let extendedIterable2 = new AsyncExtendedIterable(["Xixon", "Toulouse", "Lisbon", "Tours"]);
result = extendedIterable2.map(it => it.toUpperCase())
.filter(it => it.startsWith("T"));
console.log("before iterating normal iterable");
for await (let it of result){
console.log(it);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment