ES2018
function *sequence(start=0) {
while(true) {
start++
yield start;
}
}
const s = sequence(20);
for(x of s) {
console.log(x);
if (x > 50) break;
}
//20
//21
//22
//23
//24
//...
//51
const fs = require('fs');
const path = require('path');
function *walk(root = '.', folders) {
try {
for (const file of fs.readdirSync(root)) {
yield *walk(path.join(root, file), folders);
}
if (folders) yield root;
} catch (error) {
if (error.code != 'ENOTDIR') throw error;
yield root;
}
}
module.exports = walk;
function *sequence(start=0) {
while(true) {
start++
yield start;
}
}
const s = sequence(20);
for(x of s) {
console.log(x);
if (x > 50) break;
}
//20
//21
//22
//23
//24
//...
//51
async function* splitLines(chunksAsync) {
let previous = '';
for await (const chunk of chunksAsync) {
previous += chunk;
let eolIndex;
while ((eolIndex = previous.indexOf('\n')) >= 0) {
const line = previous.slice(0, eolIndex);
yield line;
previous = previous.slice(eolIndex+1);
}
}
if (previous.length > 0) {
yield previous;
}
}
const p = new Promise((resolve, reject) => {
fetch('cnn.com').then(resolve)
});
p.then((contentOfCNN) => {
return ignoreContent(contentOfCNN);
})
.then((resultOfIgnoring) => {
return doSomethingElse(resultOfIgnoring);
})
.then((resultOfSomethingElse) => {
return doAnotherThingButNotTheSame(resultOfSomethingElse);
})
.then((resultOfAnotherThing) => {
return OkOneLastThingIPromise(resultOfAnotherThing);
})
.then((resultOfOneLastThing) => {
return resultOfOneLastThing;
})
Oh god, make it stawp
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
};
var add = async function(x) { // async function expression assigned to a variable
var a = await resolveAfter2Seconds(20);
var b = await resolveAfter2Seconds(30);
return x + a + b;
};
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function
But what about iteration???
var promises = [];
for(var i = 0; i < 5; i++) {
var promise = $http.get('/data' + i);
promises.push(promise);
}
$q.all(promises).then(doSomethingAfterAllRequests);
//https://daveceddia.com/waiting-for-promises-in-a-loop/
Not terrible, but far from pretty and the true meaning of the code is hidden behind the semantics of promises.
//http://2ality.com/2016/10/asynchronous-iteration.html
//The interface:
interface AsyncIterable {
[Symbol.asyncIterator]() : AsyncIterator;
}
interface AsyncIterator {
next() : Promise<IteratorResult>;
}
interface IteratorResult {
value: any;
done: boolean;
}
//Usage:
async function f() {
for await (const x of createAsyncIterable(['a', 'b'])) {
console.log(x);
}
}
// Output:
// a
// b
Finally!
function createRejectingIterable() {
return {
[Symbol.asyncIterator]() {
return this;
},
next() {
return Promise.reject(new Error('Problem!'));
},
};
}
(async function () { // (A)
try {
for await (const x of createRejectingIterable()) {
console.log(x);
}
} catch (e) {
console.error(e);
// Error: Problem!
}
})(); // (B)
//http://2ality.com/2016/10/asynchronous-iteration.html
Recently at work we needed to import very large chunks of client data into our production database.
Being a poor startup, we can't afford beefy servers with huge amounts of RAM so that we can simply load the files into memory and process away.
We were forced to use the small, free tier servers offered by AWS, which meant fitting the processing into no more than a couple gigs of RAM at best.
What to do???
Stream it, of course! (with generators)
const fs = require('fs')
async function* get_lines(path) {
const stream = fs.createReadStream(path, {
encoding: 'utf8', // null -> buffers, 'utf8' -> strings with that encoding
highWaterMark: 1024 // maximum size of each chunk (buffer or string)
});
counter = 0
for await (const chunk of stream) {
counter++
// console.log(`Read: ${chunk}`);
yield `${counter}: ${chunk}\n`;
}
}
async function main() {
lines = get_lines('./lorem.txt');
for await (const line of lines) {
console.log(line);
}
}
main();