├── .gitignore ├── 0-event-loop.ts ├── 1-consume-promise.ts ├── 2-create-promise.ts ├── 3-async-await.ts ├── 4-concurrency.ts ├── 5-error-handling.ts ├── 6-sugar.ts ├── README.md ├── index.ts ├── log.ts ├── package-lock.json ├── package.json ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vscode/ 3 | dist/ -------------------------------------------------------------------------------- /0-event-loop.ts: -------------------------------------------------------------------------------- 1 | // L1 2 | console.log('🥪 Synchronous 1'); 3 | 4 | // L2 5 | setTimeout(_ => console.log(`🍅 Timeout 2`), 0); 6 | 7 | // L3 8 | Promise.resolve().then(_ => console.log('🍍 Promise 3')); 9 | 10 | // L4 11 | console.log('🥪 Synchronous 4'); 12 | -------------------------------------------------------------------------------- /1-consume-promise.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | 3 | const promise = fetch('https://jsonplaceholder.typicode.com/todos/1'); 4 | 5 | promise 6 | .then(res => res.json()) 7 | .then(todo => { 8 | throw new Error('uh oh'); 9 | return todo; 10 | }) 11 | .then(todo => console.log('😛', todo.title)) 12 | .catch(err => console.error('😭', err)); 13 | 14 | console.log('🥪 Synchronous'); 15 | 16 | -------------------------------------------------------------------------------- /2-create-promise.ts: -------------------------------------------------------------------------------- 1 | 2 | const tick = Date.now(); 3 | const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`); 4 | 5 | const codeBlocker = () => { 6 | 7 | // Blocking 8 | 9 | // let i = 0; 10 | // while(i < 1000000000) { i++;} 11 | 12 | // return '🐷 billion loops done'; 13 | 14 | 15 | // Async blocking 16 | 17 | // return new Promise((resolve, reject) => { 18 | 19 | // let i = 0; 20 | // while(i < 1000000000) { i++;} 21 | 22 | // resolve('🐷 billion loops done'); 23 | // }) 24 | 25 | 26 | // Non-blocking 27 | 28 | return Promise.resolve().then(v => { 29 | let i = 0; 30 | while(i < 1000000000) { i++; } 31 | return '🐷 billion loops done'; 32 | }) 33 | 34 | } 35 | 36 | log('🥪 Synchronous 1'); 37 | 38 | 39 | codeBlocker().then(log) 40 | 41 | 42 | log('🥪 Synchronous 2'); 43 | -------------------------------------------------------------------------------- /3-async-await.ts: -------------------------------------------------------------------------------- 1 | // Basic 2 | export const getFruit = async name => { 3 | const fruits = { 4 | pineapple: '🍍', 5 | peach: '🍑', 6 | strawberry: '🍓' 7 | }; 8 | 9 | return fruits[name]; 10 | }; 11 | 12 | getFruit('peach').then(console.log); 13 | 14 | // Async + Await 15 | 16 | export const makeSmoothie = async () => { 17 | const a = await getFruit('pineapple'); 18 | const b = await getFruit('strawberry'); 19 | 20 | return [a, b]; 21 | }; 22 | 23 | const makeSmoothie2 = () => { 24 | let a; 25 | return getFruit('pineapple') 26 | .then(v => { 27 | a = v; 28 | return getFruit('strawberry'); 29 | }) 30 | .then(v => [a, v]); 31 | }; 32 | -------------------------------------------------------------------------------- /4-concurrency.ts: -------------------------------------------------------------------------------- 1 | import { getFruit } from './3-async-await'; 2 | 3 | const makeSmoothieFaster = async() => { 4 | const a = getFruit('pineapple'); 5 | const b = getFruit('strawberry'); 6 | 7 | const smoothie = await Promise.all([a, b]) 8 | 9 | return smoothie; 10 | } 11 | 12 | 13 | const fruitRace = async() => { 14 | const a = getFruit('pineapple'); 15 | const b = getFruit('strawberry'); 16 | 17 | const winner = await Promise.race([a, b]) 18 | 19 | return winner; 20 | } 21 | 22 | // fruitRace().then(log) 23 | // fruitRace().then(log) 24 | // fruitRace().then(log) 25 | // fruitRace().then(log) 26 | // fruitRace().then(log) 27 | -------------------------------------------------------------------------------- /5-error-handling.ts: -------------------------------------------------------------------------------- 1 | import { getFruit } from './3-async-await'; 2 | 3 | const badSmoothie = async() => { 4 | try { 5 | 6 | const a = getFruit('pineapple') 7 | const b = getFruit('strawberry'); 8 | const smoothie = await Promise.all([a, b]) 9 | 10 | throw 'broken!' 11 | 12 | return smoothie; 13 | 14 | } catch(err) { 15 | console.log(err) 16 | // return `😬 We are going to be fine...` 17 | throw `💩 It's broken!` 18 | } 19 | } -------------------------------------------------------------------------------- /6-sugar.ts: -------------------------------------------------------------------------------- 1 | import { getFruit } from './3-async-await'; 2 | 3 | const fruits = ['peach', 'pineapple', 'strawberry']; 4 | 5 | const fruitLoop = async () => { 6 | for (const f of fruits) { 7 | const emoji = await getFruit(f); 8 | log(emoji); 9 | } 10 | }; 11 | 12 | const fruitInspection = async () => { 13 | if ((await getFruit('peach')) === '🍑') { 14 | console.log('looks peachy!'); 15 | } 16 | }; 17 | 18 | import fetch from 'node-fetch'; 19 | 20 | const getTodo = async () => { 21 | const res = await fetch('https://jsonplaceholder.typicode.com/todos/1'); 22 | 23 | const { title, userId, body } = await res.json(); 24 | 25 | console.log(title, userId, body); 26 | }; 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Async Await Pro Tips 2 | 3 | Learn how to [write beautiful async code](https://youtu.be/vn3tm0quoqE) 4 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codediodeio/async-await-pro-tips/39dd06052c27606b8e3188c12205535fc7eec126/index.ts -------------------------------------------------------------------------------- /log.ts: -------------------------------------------------------------------------------- 1 | export const logTimeout = n => console.log(`🍅 Timeout ${n}`); 2 | export const logPromise = n => console.log(`🍍 Promise ${n}`); 3 | export const logSync = n => console.log(`🥪 Synchronous ${n}`); 4 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "async", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "10.11.5", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.11.5.tgz", 10 | "integrity": "sha512-3j1EFLfrjYRHRFjBb+RIXXwr1YGzcfpQVMP39thZa6tMY+JjVgQddPF+hsdV800JqbuLwpwAWclDpbGSAw44vQ==" 11 | }, 12 | "@types/node-fetch": { 13 | "version": "2.1.2", 14 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.1.2.tgz", 15 | "integrity": "sha512-XroxUzLpKuL+CVkQqXlffRkEPi4Gh3Oui/mWyS7ztKiyqVxiU+h3imCW5I2NQmde5jK+3q++36/Q96cyRWsweg==", 16 | "requires": { 17 | "@types/node": "*" 18 | } 19 | }, 20 | "node-fetch": { 21 | "version": "2.2.0", 22 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz", 23 | "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "async", 3 | "version": "1.0.0", 4 | "description": "`git clone ` `tsc && node dist/index.js`", 5 | "main": "loops.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@types/node-fetch": "^2.1.2", 14 | "node-fetch": "^2.2.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "sourceMap": true, 6 | "outDir": "dist", 7 | "lib": ["dom", "es2015"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "quotemark": [true, "single"] 4 | } 5 | } 6 | --------------------------------------------------------------------------------