The

3

Stages

of

insanity!

Writing JavaScript!

Let's talk about asynchronous in JavaScript

synchronous flows are easy ...

synchronous flows are easy ...

function getStockPrice(name) {
    let symbol = getStockSymbol(name);
    let price = getSymbolPrice(symbol);
    return price;
}

synchronous flows are easy ...

Blocking is easy :D

function getStockPrice(name) {
    let symbol = getStockSymbol(name);
    let price = getSymbolPrice(symbol);
    return price;
}

but we don't want to block!

function getStockPrice(name) {
    let symbol = getStockSymbol(name, (err, price) => {...});
    let price = getSymbolPrice(symbol, (err, price) => {...});
    return price;
}

we want to wait :)

The Pyramid of DOOM!

The Pyramid of DOOM!

1 function getStockPrice(name, cb) {
2     getStockSymbol(name, (error, symbol) => {
3         if (error) {
4             cb(error);
5         } else {
6              getSymbolPrice(symbol, (error, symbol) => {
7                 if (error) {
8                     cb(error);
9                 } else {
10                     cb(price);
11                 }
12             });
13         }
14     });
15 }

Promise Waiting

1 function getStockPrice(name) {
2    return getStockSymbol(name).
3            then(symbol => getSymbolPrice(symbol));
4 }
5
6 getStockPrice("Yolo").
7    then(
8        price => console.log(price),
9        error => console.error(error)
10    );

Promise chain - HELL

1 remotedb.allDocs({
2   include_docs: true,
3   attachments: true
4 }).then(function (result) {
5   var docs = result.rows;
6   docs.forEach(function(element) {
7     localdb.put(element.doc).then(function(response) {
8       alert("Pulled doc with id " + element.doc._id + " and added to local db.");
9     }).catch(function (err) {
10       if (err.name == 'conflict') {
11         localdb.get(element.doc._id).then(function (resp) {
12           localdb.remove(resp._id, resp._rev).then(function (resp) {
13 // et cetera...

Promise 

Promise 

A better looking Promise chain - HELL

1 remotedb.allDocs(...).then(function (resultOfAllDocs) {
2   return localdb.put(...);
3 }).then(function (resultOfPut) {
4   return localdb.get(...);
5 }).then(function (resultOfGet) {
6   return localdb.put(...);
7 }).catch(function (err) {
8  console.log(err);
9 });

try and handle the error cases on this one.

What we want vs. what we have :)

function getStockPrice(name) {
    let symbol = getStockSymbol(name);
    let price = getSymbolPrice(symbol);
    return price;
}
function getStockPrice(name) {
    return getStockSymbol(name).
            then(symbol => getSymbolPrice(symbol));
}

getStockPrice("Yolo").
    then(
        price => console.log(price),
        error => console.error(error)
    );

Still not up to date - the new way of waiting...

function* getStockPrice(name) {
    let symbol = yield getStockSymbol(name);
    let price = yield getSymbolPrice(symbol);
    return price;
}

Generator functions

A generator is  a function that can return multiple values.

Generator functions

let MAX_NUM = 99999;
let MIN_NUM = -9999;

function* generateNumbers() {
    while(MAX_NUM > MIN_NUM) {
        yield MAX_NUM;
        MAX_NUM -= 1;
    }
    return MIN_NUM;
}

Generator functions

let MAX_NUM = 99999;
let MIN_NUM = -9999;

function* generateNumbers() {
    while(MAX_NUM > MIN_NUM) {
        yield MAX_NUM;
        MAX_NUM -= 1;
    }
    return MIN_NUM;
}

let iterator = generateNumbers();
console.log(iterator.next());
// { value: 99999, done: false}

console.log(iterator.next());
// { value: 99998, done: false}

console.log(iterator.next());
// { value: 99997, done: false}

.
.
.

console.log(iterator.next());
// { value: -9999, done: true}
The

state

machine

Generator - split personality

function* generator(number) {
    let x = yield number;
    return x;
}

let iterator = generator(4);

console.log(iterator.next(5));
// { value: 4, done: false}

console.log(iterator.next());
// { value: 5, done: true}
The

state

machine

Generator - the untapped power

function* getStockPrice(number) {
    let symbol = yield getStockSymbol(name);
    let price = yield getSymbolPrice(symbol);
    return price;
}

function spawn (generator) {
    return  new Promise((accept, reject) => {
    let onResult = lastPromiseResult => {
            let {value, done} = generator.next(lastPromiseResult);
            if (!done) {
                value.then(onResult, reject);
            } else {
                accept(value);
            }
        };
    });
    onResult();
}

spawn(getStokPrice("Yolo")).then(console.log(price),console.error(error));

Generator - the untapped power

All of that is a little to much and so what do we do ?

Get to the future... which is now!

Async - wirting code that looks like it blocks but it actually waits.

async function getStockPrice(name) {
    let symbol = await getStockSymbol(name);
    let price = await getSymbolPrice(symbol);
    return price;
}

Async - is this the promise land ?

Async - maybe ?! async I/O

function* getStocks() {
    let reader = new FileReader("stocks.txt");
    
    try {
        while(!render.eof) {
            yield JSON.parse(reader.readLine());
        }
    } finally {
        render.close();
    }
}

async function writeStockInfo() {
    var writer = new FileWriter("stocksAndPrices.txt");
    try {
        for(let name of getStocks()) {
            let price = await getStockPrice(name);
            writer.writeLine(JSON.stringify({name, price}));
        }
    } finally {
        writer.close();
    }
}

we can't wait withing an await

Async - maybe ?! async I/O

/* 
    Read stocks form a file and 
    returns an Array of Strings.
*/
async function getStocks() { ... }

async function writeStockInfo() {
    var writer = new FileWriter("stocksAndPrices.txt");
    try {
        await getStocks().map( async line => {
            for(let name of getStocks()) {
                let price =  await getStockPrice(name);
                writer.writeLine(JSON.stringify({name, price}));
            }
        });
    } finally {
        writer.close();
    }
}

we can't use async within an async function

We are missing something ...

We are missing something ...

Observable

Observable

async function* getStocks() {
    let reader = new AsyncFileReader("stocks.txt");
    
    try {
        while(!render.eof) {
           await yield JSON.parse( await reader.readLine());
        }
    } finally {
        await render.close();
    }
}

async function writeStockInfo() {
    var writer = new AsyncFileWriter("stocksAndPrices.txt");
    try {
        for(let name of getStocks()) {
            let price =  await getStockPrice(name);
            await writer.writeLine(JSON.stringify({name, price}));
        }
    } finally {
        await writer.close();
    }
}

async function* - the future!

Observable

To insanity and beyond!

Observable

To insanity and beyond!

Copy of deck

By Stefan Hagiu

Copy of deck

  • 564