Last active
February 16, 2020 15:17
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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