2. Async JS

Async JS

The call stack

  • Mechanism that JS uses to keep track where it is in a script. Last thing in, first thing out.
  • To see the call stack in action use Sources in Chrome

Web API and Single Threaded

  • http://latentflip.com/loupe
  • JS is single threaded
  • The browser come with web API that can handle tasks in background
  • setTimeout is a web api function (-> callback function)
  • callback is used to delay execution

Promises

  • Objects that represents the eventual completion or failure of an asynchronous operation
  • Attach callback to the promise instead of passing them into a function
const request = dummyReqPromise('google.com/api')
request.then( (data) => {
    console.log('PROMISE 1 RESOLVED')
    console.log(data)
})
.then( (data) => {
    console.log('PROMISE 2 RESOLVED')
})
.then( (data) => {
    console.log('PROMISE 3 RESOLVED')
})
.catch( (err) => {
    console.log('PROMISED REJECTED')
    console.log(err)
})

Creating promises

const fakeRequest = (url) =>{
    return new Promise((resolve, reject)=>{
        setTimeout(() => {
            resolve('something');
        }, 1000);
    })        
}

fakeRequest('/cats/1')
    .then( (data) => {
        console.log("Done with request")
        console.log(data)
    })

Async Function

  • async functions always return a promise
const asyncFunction = async () => {
    //returns a promise
    return 'aaaa' //resolved value
}
  • to reject a promise: throw an error
    const asyncFunction = async () => {
      throw 'random error'
    }
    
  • login example ```chsarp const login = async (username, password) => { if (!username || !password) throw ‘Missing Credentials’ if (password === ‘1234’) return ‘Welcome’ throw ‘Invalid Password’; }

login(‘aaa’, ‘1234’) .then(msg => { console.log(‘logged in’); console.log(msg); }) .catch(err =>{ console.log(“error”) console.log(err) })


### Await keyword

- wait for a promise to be resolved before continuing with the async function
```csharp
const changeBackColor = (color, delay) =>{
    return new Promise((resolve, reject) =>{
        setTimeout( () => {
            document.body.style.backgroundColor = color;
            resolve();
        }, delay)
    }

    )
}

async function rainbow(){
    await changeBackColor('red', 1000)
    await changeBackColor('blue', 1000)
    await changeBackColor('green', 1000)
}

Rejected Promised

  const fakeRequest = (url) =>{
    return new Promise((resolve, reject) => {
        const delay = Math.floor(Math.random() * 4500)+500;
        setTimeout(() => {
           if (delay > 4000) {
               reject ('connection timeout')
           }
           else{
               resolve (`here is your data ${url}`)
           }
        }, delay);
    })
}


async function makeTwoRequests(){
    try{
        let data1 = await fakeRequest('/apple1')
        console.log(data1)
        let data2 = await fakeRequest('/apple2')
        console.log(data2)
    }   
    catch(e){
        console.log('error is', e);
    }
}

AsyncJavascriptAndXml requests

  • make request after the page has been loaded
  • jsonformatter.curiousconcept.com
  • JSON.parse(data) converts a string into json object

Fetch API

  • fetch returns a promise:
fetch('https://api.google.com')
    .then(res => { 
        console.log("RESPONSE", res)
        return res.json();
    })
    .then( data => {
        console.log(data.ticker.price);
    })
    .catch(e => {
        console.log('error');
    })
  • using async function:
const fetchBitcoinPrice = async () => {
try{
    const res = await fetch('https://api.google.com');
    const data = await res.json();
    console.log(data.ticker.price);
    }
catch(e){
    console.log(e);
    }
}

Axios

  • easier than use fetch
axios.get('https://api.cryptonator.com/api/ticker/btc-usd')
    .then( res => {
        console.log(res.data.ticker.price);
    })
    .catch( err => {
        console.log("Error", err);
    })
const fetchBTCPrice = async () => {
    try{
        const res = await axios.get('https://api.cryptonator.com/api/ticker/btc-usd');
        console.log(res.data.ticker.price);
    }
    catch (e) {
        console.log("Error", e);
    }
}

Setting Headers

  • set headers to get desired response type (html, json…)
const getDadJoke = async () => {
    const config = {headers:{Accept: 'application/json'}}
    const res = await axios.get('https://icanhazdadjoke.com/', config);
    return res.data.joke;
}

const jokeBtn = document.querySelector('#jokeBtn')
const jokeText = document.querySelector('#jokeText')

jokeBtn.addEventListener('click', async () => {
    try{
        await console.log('clicked')
        await getDadJoke().then(res => {            
            jokeText.textContent = res;
        });
    }
    catch(err){
        jokeText.textContent = "Error joke not available";
    }
    })    
Written on April 1, 2021