Falling in love with async await in love with async await.pdf · Falling in love with async await...

Post on 03-Oct-2020

21 views 0 download

Transcript of Falling in love with async await in love with async await.pdf · Falling in love with async await...

FALLING IN LOVE WITH ASYNC-AWAIT

Atishay Jain, Senior Computer Scientist, AdobeByetconf JS 2019

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

JavaScript

Image by Nathan on Flickr

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Agenda■ About me

■ The async-await paradigm

■ A beginners walk-through of async await– Callback vs promise vs async await– The program flow

■ Intermediate async-await– A detour to promises– Async guarantees– The program flow–Wrapping asynchronous functions

■ Advanced async-await– Exploiting the promises underneath– Exploiting callbacks deep down

■ Conclusion

Image from gyfcat

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

About Me● Work in San Francisco.● Crazy about the web

● Working on web since the Flash & IE6 days.

● Have worked on Desktop (Adobe InDesign), and on Mobile (Adobe Capture)

● Author of VS Code’s “All Autocomplete” plugin

● Rewrote my website for the nth time last year) - https://atishay.me (Perf score 100)

● Guest author at CSS-Tricks● Ship node based desktop software to

millions of Creative Cloud users● Use these techniques(& much more) in

daily life● Doing asynchronous node.js since Node

0.6.

THE ASYNC-AWAIT PARADIGM

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Serial Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Conditionals Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Conditionals Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Conditionals Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Conditionals Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Conditionals Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Conditionals Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Loop

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Function

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Async

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The concept of async-await

Event Dispatch

BEGINNING ASYNC-AWAIT

A callback vs promise vs async await

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A callback vs promise vs async awaitfunction work(data, cb) {

db.connect((err) => {if(err) {return cb(err);}db.query(query1, (err, result1) =>{

if(err) { return cb(err) }db.query(query2, cb);

});});

}

function work() {return db.connect().then(() => {

return db.query(query1);}).then((result1)=> {

return db.query(query2);});

}

async function work() {await db.connect();result1 = await db.query(query1);return await db.query(query2);

}

Callback Promises

async await

BEGINNING ASYNC-AWAIT

The Program Flow

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

async function foo() {...await foo1();...if(await foo2()) {

...await foo3()...

}for(...) {

await foo4(...);}...

}

The natural waterfall model

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

x = [...]x.forEach(async y => {

await foo(y);});

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

// Wrong will return promise to // forEach and not waitx = [...]x.forEach(async y => {

await foo(y);});

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

// Right – will wait for each// await in sequential orderx= [...];for(y of x) {

await foo(y)}

Using for-of

// Wrong will return promise to // forEach and not waitx = [...]x.forEach(async y => {

await foo(y);});

Note: for..in does not make it to the JavaScript Good parts and should be avoided in the favor of for..of where possible.

INTERMEDIATE ASYNC-AWAIT

A detour to promises

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A detour to promises

Image from Prexels

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A detour to promises

■ Promises have a then/catch/finally.

async function f() {...}await f()

.then((resp) => doSomething(resp))

.catch((e) => handleError(e))

.finally(() => cleanup());

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A detour to promises

■ There is a concept of unhandled rejection.

process.on("unhandledRejection",...);

window.addEventListener("unhandledrejection", ...);

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A detour to promises

■ Use Promises to convert a callback based method to async

function x(data, callback) {y.doSomething(data, (err, z) => {

if (err) { return callback(err); }processed = somePostProcessing(z);callback(null, processed)

});}

x(data, (err, processed) => { });

Conversion guide: https://atishay.me/blog/2018/08/25/from-callbacks-to-async-await/

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A detour to promises

■ Use Promises to convert a callback based method to async

function x(data, callback) {y.doSomething(data, (err, z) => {

if (err) { return callback(err); }processed = somePostProcessing(z);callback(null, processed)

});}

function x(data) {return new Promise((resolve, reject) => {

y.doSomething(data, (err, z) => {if (err) {return reject(err);}processed = somePostProcessing(z);resolve(processed);

});});

const processed = await x(data);x(data, (err, processed) => { });

Conversion guide: https://atishay.me/blog/2018/08/25/from-callbacks-to-async-await/

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

A detour to promises

■ Use Promises to convert a callback based method to async

function x(data, callback) {y.doSomething(data, (err, z) => {

if (err) { return callback(err); }processed = somePostProcessing(z);callback(null, processed)

});}

async function x(data) {return new Promise((resolve, reject) => {

y.doSomething(data, (err, z) => {if (err) {return reject(err);}processed = somePostProcessing(z);resolve(processed);

});});

const processed = await x(data);x(data, (err, processed) => { });

Conversion guide: https://atishay.me/blog/2018/08/25/from-callbacks-to-async-await/

INTERMEDIATE ASYNC-AWAIT

The Program Flow

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

Delayed await

async foo() {...await fetch()...

}

const p = foo();// Do some parallel tasks...await p;

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

Running stuff in parallel

const tasks = [fetch(p1),fetch(p2),fetch(p3)

];

responses = await Promise.all(tasks);

Note: This will return quickly in case of exceptions. There are ways to workaround this, while the standards committee is working on Promise.allSettled to provide the easy solution.

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

Using array.map

await Promise.all([...].map(async x => {...await foo(x);...

}));

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

Racing functions

// setTimeout async versionconst timeout = async (time) => new Promise(resolve => setTimeout(resolve, time));

// Adding a timeout to fetchawait Promise.race([fetch(...), timeout(2000)]);

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

The program flow

Errors without try...catch

function handleError(error) {console.log(error);return fallbackFoo2Response;

}

await foo1(...);await foo2(...).catch(handleError);await foo3(...)

await Promise.all([].map(async () => {

...}).map(x => x.catch(e => e))

);

ADVANCED ASYNC-AWAIT

Async guarantees

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Async guarantees

Image from IMDB

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Async guaranteesundefined = true;

foo.apply(window, arguments)

function(cb) {x((err) => {

if(err) { callback(err); }callback(true);

})}

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Async guarantees

■ It always returns once

■ There is only one return value

■ It is always a promise

undefined = true;

foo.apply(window, arguments)

function(cb) {x((err) => {

if(err) { callback(err); }callback(true);

})}

ADVANCED ASYNC-AWAIT

Wrapping asynchronous functions

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

Image from Pixabay

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

Shared data problem

Pay $20 Take $20

$ 100$ 100$ 80$ 120

Read

Read

Write

Write

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

Shared data and locks

let mutex = false;

async lock() {while(mutex) { await timeout(100);}mutex = true;

}

unlock() {mutex = false;

}

async a() {await lock();await fs.readFile(file);await fs.writeFile(file);unlock()

}

async b() {await lock()await fs.readFile(file);await fs.writeFile(file);unlock();

}

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

Fixing forgotten lock call problem

async a() {await lock();await fs.readFile(file);await fs.writeFile(file);

}

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

Fixing forgotten lock call problem

async a() {return await transaction(async () =>

{await fs.readFile(file);await fs.writeFile(file);

});}

async a() {await lock();await fs.readFile(file);await fs.writeFile(file);

}

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

async transaction(method) {lock();const value = await method();unlock();return value;

}

async transaction(method) {await lock();const value = await method().catch(e => {

unlock();throw e;

});unlock();return value;

}

Wrapping asynchronous functions

The transaction wrapper

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

A better way - the time wrapper

async time(key, method) {console.time(key);return await method().finally(() => {

console.timeEnd(key);});

}

// Usageawait time('myMethod', async ()=> {

//do your work})

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Wrapping asynchronous functions

Include context

async time(key, method) {const context = {};console.time(key);return await method(context).finally(() => {

console.timeEnd(key);fetch(url, {body: context});

});}

// Usageawait time(async (context)=> {

//do your workcontext.x = "some result;

});

ADVANCED ASYNC-AWAIT

Exploiting the promises underneath

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting promises in async

The Parallel calls problem

Image from gifer

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting promises in async

Doing it once

function get(cb) {if (data) {

cb(data);} else {

callbacks.push(cb);}if (callbacks.length === 1) {

...callbacks.forEach(cb => cb(data));

}}

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting promises in async

Memoize method

let get = memoize(async () => {...return data;

});

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting promises in async

Lodash - Memoize methodhttps://github.com/lodash/lodash/blob/master/memoize.js

1 function memoize(func, resolver) {2 const memoized = function(...args) {3 const key = resolver ? resolver.apply(this, args) : args[0]4 const cache = memoized.cache56 if (cache.has(key)) {7 return cache.get(key)8 }9 const result = func.apply(this, args)10 memoized.cache = cache.set(key, result) || cache11 return result12 }13 memoized.cache = new Map();14 return memoized15 }

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting promises in async

Reuse the promise only if pending

9.1 if (result instanceof Promise) {9.2 result.state = 'pending';9.3 result.then(() => result.state = 'resolved’)9.4 .catch(() => result.state = 'rejected’);9.5 }

6 if (cache.has(key)) {6.1 let x = cache.get(key);6.2 if (x instanceof Promise) {6.3 if (x.state === 'pending') {7 return x;7.1 }7.2 }8 }

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting promises in async

Creating decorator for memoize

// Convert to ES6 Decoratorfunction Memoize() {

return function (target, functionName, descriptor) {descriptor.value = memoize(target[functionName]);

};}

@Memoizeasync get() {

...return data;

}

ADVANCED ASYNC-AWAIT

Exploiting callbacks deep down

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting callbacks deep down

Reader-Writer Problem

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting callbacks deep down

Reader-Writer Problem

Storage

Reader

Reader

Reader

Writer

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting callbacks deep down

Read-Write Lock API

await lock.read(async ()=> {// Do reading

});

await lock.write(async () => {// Do writing

});

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting callbacks deep downclass Lock {

pendingReads = []pendingWrites = []async read(func) { // Cannot use await here

return new Promise(resolve => {pendingReads.push({func, cb:resolve});this.perform();

});}async write(func) { // Cannot use await here

return new Promise(resolve => {pendingWrites.push({func, cb: resolve});this.perform();

}}perform() {

...}

}Structure of the Lock class

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Exploiting callbacks deep downperform() {

if (this.state === 'None' && this.pendingWrites.length > 0) {this.state = 'Write’;const {func, cb} = this.pendingWrites.shift();func().finally(() => {

cb(); this.state = 'None’; this.perform();}

}

if (this.state !== 'Write' && this.pendingReads.length > 0) {this.pendingReads.forEach(({func, cb})=> {

this.state = 'Read’;this.readInProgess++;func().finally(() => {

cb();this.readInProgess--;if (this.readInProgess === 0) { this.state === 'None’; }this.perform();

})});

}

}readInProgess = 0state = 'None’

Structure of the Lock class

CONCLUSION

Falling in love with async await Atishay Jain<contact@atishay.me> https://atishay.me

Conclusion

■ Where callbacks rule:– addEventListener– Method Wrappers (can be @decorators as well).

■ Where Promises rule– Short hands with async

■ Where async await rule– Everywhere else

Image from giphy

THANK YOUAtishay Jain

https://atishay.mecontact@atishay.me