Return to site

Promesses

Dealing with asynchronous methods

· angular

Using Promises

Communication with APIs is one of the most fundamental functions in modern JavaScript programming; however, in order to use APIs properly in your application you have to be able to use Asynchronous methods. Synchronous code executes one after another depending on how it is defined in the file, and is the standard method of operation for JavaScript and TypeScript. Asynchronous code; on the other hand, may be defined within other code, and will execute when a specified delay occurs or a resource is finished loading.

 

TypeScript offers two different methods of dealing with asynchronous methods: Promises and Async/Await - which is a new standard introduced in ES7 that TypeScript allows you to use. In this lab, we are going to leverage asynchronous code to fetch cute little robot avatar icons for our movingElement items that we created in the previous labs. We will be doing the same method two ways, first with Promises, and then with the new Async/Await standard.

 

In this exercise, we are going to fetch our avatars with Promises.

 

1.       Copy your advancedTypeScriptLab_animated folder, and name the copy advancedTypeScriptLab_promise. First, open up your index.html file in your advancedTypeScriptLab_promise folder in Visual Studio Code.

 

2.       Since we are going to be using the fetch API - a new way of creating server requests in JavaScript - we need to make sure to add a polyfill to our index.html file in case fetch isn't available in your browser. A polyfill is a script to ensure that a newer feature implemented in modern browsers is available in older browsers. To do this, we are going to add a script tag above the reference to advancedTypeScriptLab.js in our index.html file referencing the CDNJS copy of the Fetch polyfill.

 

<html>

    <body>

        <script src='https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js'></script>

        <script src='advancedTypeScriptLab.js'></script>

    </body>

</html>

 

3.       Save your index.html file, and then open up your advancedTypeScriptLab.ts file in your advancedTypeScriptLab_promise folder in Visual Studio Code.

 

4.       Let's make a method called getAvatar_Promise.

 

function getAvatar_Promise (elem: HTMLElement) {  

}

 

Note that we are going to be passing our HTMLElement from the movingElement class, so we have the call signature typed in that fashion.

 

5.       Now, in order to make our little robots, we are going to be using the RoboHash API. We are going to set our element's backgroundImage to the URL of our RoboHash, then append it to the document.body.

 

function getAvatar_Promise (elem: HTMLElement) {   

    let avatar = 'https://robohash.org/set_set3/somerobot?size=60x60'

    elem.style.backgroundImage = 'url("' + avatar + '")';

    document.body.appendChild(elem);

}

 

This is all fine, but if we were to run this code, all of our robots would look the same. That's boring! Let's make this more interesting and make each robot generated completely different.

 

6.       In order for our robots to be randomly generated, RoboHash needs a different string passed to the image name, replacing where we put somerobot in the avatar variable value. We could just generate a string at random, but what fun is that? Instead, let's name our robots using an API that returns random user information - UINames. First - we will call UINames using fetch.

 

function getAvatar_Promise (elem: HTMLElement) {

    fetch('https://uinames.com/api/')

    let avatar = 'https://robohash.org/set_set3/somerobot?size=60x60'

    elem.style.backgroundImage = 'url("' + avatar + '")';

    document.body.appendChild(elem);

}

 

7.       The fetch command returns what is called a Promise. If you were to assign this value to a variable and attempt to use it, it wouldn't work because the value hasn't returned by the server by the time the next line is called. In order to use a value from a Promise, we need to use the .then() property of the promise, which will contain the response from the server.

 

function getAvatar_Promise (elem: HTMLElement) {

    fetch('https://uinames.com/api/').then(function(response) {

        return response.json();

    })

    let avatar = 'https://robohash.org/set_set3/somerobot?size=60x60'

    elem.style.backgroundImage = 'url("' + avatar + '")';

    document.body.appendChild(elem);

}

 

The response.json() method transforms the fetch response into a JSON object ready for your code to use. But we still aren't quite there yet!

 

8.       Even though we are returning response.json() from our .then(), this return is still a Promise. In order to use the JSON object returned from the fetch properly, we need to chain another .then() to use that value. Then we can get access to the actual data from the server - in this case we are after the name property. Let's go ahead and make the robots introduce themselves when they are about to show up on the screen.

 

function getAvatar_Promise (elem: HTMLElement) {

    fetch('https://uinames.com/api/').then(function(response) {

        return response.json();

    }).then(function(response) {

        alert('Hi! My name is ' + response.name);       

    })

    let avatar = 'https://robohash.org/set_set3/somerobot?size=60x60'

    elem.style.backgroundImage = 'url("' + avatar + '")';

    document.body.appendChild(elem);

}

 

Now the robots are announcing themselves, but they still aren't using the name to generate the avatar, and they are still being added to the DOM before the server's response is called. The code below the .then() chain is still running synchronously.

 

9.       To fix that problem, let's move the rest of the code into the .then() block, and concatenate the response.name property into our avatar URL.

 

function getAvatar_Promise (elem: HTMLElement) {

    fetch('https://uinames.com/api/').then(function(response) {

        return response.json();

    }).then(function(response) {

        alert('Hi! My name is ' + response.name);

        let avatar = 'https://robohash.org/set_set3/'+ response.name +'?size=60x60'

        elem.style.backgroundImage = 'url("' + avatar + '")';

        document.body.appendChild(elem);

    })

}

 

10.   Finally, let's adjust the iterator from the previous lab for (let elem of standardElements) to replace document.body.appendChild(elem) with a call to this function. Oh, and let's go ahead and remove the green background too.

 

for (let elem of standardElements) {

    elem.style.width = "60px"

    elem.style.height = "60px"

    elem.style.margin = "5px"

    let elemClass = new movingElement(elem);   

    getAvatar_Promise(elemClass.element);

}

 

11.   Save your file and compile with CTRL+Shift+B since we set up our default compile task in the previous lab.

 

12.   Open your index.html file in the browser, and you should first see each robot announce itself by name, then after a short while (the image does have to load), it will appear on the screen. When they've all loaded, it should look something like this:

 

 

Hover over them, watch them spin around, and click on them to watch them move back and forth.

 

Now you have some cute little spinning robot heads! In our next exercise, we will convert our function over to using the Async/Await Method.