# Asynchronous JavaScript

### Experiences from my personal journey

### Content

- About me
- Introduction
- Callbacks
- Promises
- async/await

### About me

Julian Tölle
Developer @ narando & TrackCode
Backend Development & Devops
Javascript for 13 months

### Introduction

Node.js and JavaScript are:

- single-threaded
- event-driven
- non-blocking

### Callbacks

Pros:
- supported everywhere
- used in Node.js standard library and most packages

Cons:
- hard to keep track of current context (callback hell)
- decentralized error handling

### Callbacks

#### Example

                  import fs from "fs";

                  fs.readFile("config.txt", (err, config) => {
                    if(err) {
                      console.error(err);
                      return;
                    }

                    console.log(config);
                  });

                  console.log("Hello World!");

### Callbacks

#### Callback Hell

                    var p_client = new Db("integration_tests_20");
                    p_client.open((err, p_client) => {
                      p_client.dropDatabase((err, done) => {
                        collection.insert({ a: 1 }, (err, docs) => {
                          collection.find({ name: "Donald" }, (err, cursor) => {
                            cursor.toArray((err, items) => {
                              test.assertEquals(1, items.length);

                              // Let's close the db​
                              p_client.close();
                            });
                          });
                        });
                      });
                    });

### Promises

Pros:
- supported mostly everywhere no IE11
- error handling

Cons:
- no variable passthrough
- only slightly less verbose

### Promises

#### Example

                  fetch("https://api.coindesk.com/v1/bpi/currentprice.json")
                    .then(res => res.json())
                    .then(res => res.bpi.USD.rate_float)
                    .then(rate => console.log(`Current BTC/USD Rate: ${rate}`))
                    .catch(err => console.error(err));

### Asynchronicity

#### with promises Pattern

                  // Parallel Execution
                  Promise.all([
                    fetch("https://api.coindesk.com/v1/bpi/currentprice.json"),
                    fetch("https://api.coindesk.com/v1/bpi/historical/close.json")
                  ]).then(([currentPrice, historicalPrices]) =>
                    console.log(currentPrice, historicalPrices)
                  ).catch(err => console.error(err));

### Promises

#### The ugly side

                  // Variable Passthrough
                  User.findOne({ name: "realDonaldTrump" })
                  .then(user => Promise.all([user, Tweets.find({ user_id: user.id })]))
                  .then(([user, tweets]) => {
                    console.log(`User ${user.name} has ${tweets.length} tweets`);
                  });

### async/await

Pros:
- easy adoption in promise-based code
- natural error handling

Cons:
- only supported since Node 7.6

### async/await

#### Example

                  async function getBtcRate() {
                    try {
                      const res = await fetch("https://api.coindesk.com/v1/bpi/currentprice.json");
                      const currentPrice = await res.json();
                      const rate = res.bpi.USD.rate_float;

                      console.log(`Current BTC/USD Rate: ${rate}`)
                    } catch (err) {
                      console.error(err);
                    }
                  }

### async/await

#### Pattern: Parallel Execution

                  // Parallel Execution
                  async function getBtcData() {
                    try {
                      const [currentPrice, historicalPrices] = await Promise.all([
                        fetch("https://api.coindesk.com/v1/bpi/currentprice.json"),
                        fetch("https://api.coindesk.com/v1/bpi/historical/close.json")
                      ])

                      console.log(currentPrice, historicalPrices)
                    } catch (err) {
                      console.error(err);
                    }
                  }

### async/await

#### Pattern: Keeping Context

                  // Don't loose access to previous results
                  async function getUserTweets({ username }) {
                    try {
                      const user = await User.findOne({ name: username });
                      const tweets = await Tweets.find({ user_id: user.id });

                      console.log(`User ${user.name} has ${tweets.length} tweets`);
                    } catch (err) {
                      console.error(err);
                    }
                  }

### async/await

#### Pattern: Functional Programming

                  // Mixing async/await with FP
                  async function getUserTweets({ users }) {
                    try {
                      const tweets = await Promise.all(
                        users.map(user => Tweets.find({ user_id: user.id }))
                      );

                      console.log(`A total of ${tweets.length} tweets for ${users.length} users has been returned`);
                      return tweets;
                    } catch (err) {
                      console.error(err);
                    }
                  }

### Summary

##### Callbacks

supported by standard library

##### Promises

foundation for async/await

##### async/await

most clear and simple code