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