Project: Weather App (v1)

Introduction

Use everything we’ve been discussing to create a weather forecast site using the weather API from the previous lesson. You should be able to search for a specific location and toggle displaying the data in Fahrenheit or Celsius.

You should change the look of the page based on the data, maybe by changing the color of the background or by adding images that describe the weather. (You could even use the Giphy API to find appropriate weather-related gifs and display them). Feel free to use promises or async/await in your code, though you should try to become comfortable with both.

  1. Set up a blank HTML document with the appropriate links to your JavaScript and CSS files.

  2. Write the functions that hit the API. You’re going to want functions that can take a location and return the weather data for that location. For now, just console.log() the information.

  3. Write the functions that process the JSON data you’re getting from the API and return an object with only the data you require for your app.

  4. Set up a simple form that will let users input their location and will fetch the weather info (still just console.log() it).

  5. Display the information on your webpage!

  6. Add any styling you like!

  7. Optional: add a ‘loading’ component that displays from the time the form is submitted until the information comes back from the API.

  8. Push that baby to github and share your solution below!

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

Async and Await (v1)

Introduction

Asynchronous code can become difficult to follow when it has a lot of things going on. async and await are two keywords that can help make asynchronous read more like synchronous code. This can help code look cleaner while keeping the benefits of asynchronous code.

For example, the two code blocks below do the exact same thing, they both get information from a server, process it, and return a promise.

function getPersonsInfo(name) {
  return server.getPeople().then(people => {
    return people.find(person => { return person.name === name });
  });
}
async function getPersonsInfo(name) {
  const people = await server.getPeople();
  const person = people.find(person => { return person.name === name });
  return person;
}

The second example looks much more like the kind of functions you are used to writing, however, did you notice the async keyword before the function declaration? How about the await keyword before server.getPeople()?

Learning Objectives

  1. How do you declare an async function?
  2. What does the async keyword do?
  3. What does the await keyword do?
  4. What is returned from an async function?
  5. What happens when an error is thrown inside an async function?
  6. How can you handle errors inside an async function?

The async keyword

The async keyword is what lets the javascript engine know that you are declaring an asynchronous function, this is required to use await inside any function. When a function is declared with async, it automatically returns a promise, returning in an async function is the same as resolving a promise, likewise, throwing an error will reject the promise.

An important thing to understand is async functions are just syntactical sugar for promises.

The async keyword can also be used with any of the ways a function can be created, said differently: it is valid to use an async function anywhere you can use a normal function. Below you will see some examples that may not be intuitive, if you don’t understand them, come back and take a look when you are done with the assignments.

  const yourAsyncFunction = async () => {
    // do something asynchronously and return a promise
    return result;
  }
 anArray.forEach(async item => {
   // do something asynchronously for each item in 'anArray'
   // one could also use .map here to return an array of promises to use with 'Promise.all()'
 });
server.getPeople().then(async people => {
  people.forEach(person => {
    // do something asynchronously for each person
  });
});

The await keyword

await is pretty simple: it tells javascript to wait for an asynchronous action to finish before continuing the function. It’s like a ‘pause until done’ keyword. The await keyword is used to get a value from a function where you would normally use .then(). Instead of calling .then() after the asynchronous function, you would simply assign a variable to the result using await, then you can use the result in your code as you would in your synchronous code.

Error Handling

Handling errors in async functions is very easy. Promises have the .catch() method for handling rejected promises, and since async functions just return a promise, you can simply call the function, and append a .catch() method to the end.

asyncFunctionCall().catch(err => {
  console.error(err)
});

But there is another way: the mighty try/catch block! If you want to handle the error directly inside the async function, you can use try/catch just like you would inside synchronous code.

async function getPersonsInfo(name) {
  try {
    const people = await server.getPeople();
    const person = people.find(person => { return person.name === name });
    return person;
  } catch (error) {
    // Handle the error any way you'd like
  }
}

Doing this can look messy, but it is a very easy way to handle errors without appending .catch() after your function calls. How you handle the errors is up to you, and which method you use should be determined by how your code was written. You will get a feel for what needs to be done over time. The assignments will also help you understand how to handle your errors.

Practice

Remember the Giphy API practice project? (If not, you should go back and complete the API lesson) We are going to convert the promise based code into async/await compatible code. Here’s a refresher of the code we are starting with:

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      img.src = response.data.images.original.url;
    });
</script>

Since await does not work on the global scope, we will have to create an async function that wraps our API call to Giphy.

<script>
  const img = document.querySelector('img');

  async function getCats() {
    fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
      .then(function(response) {
        return response.json();
      })
      .then(function(response) {
        img.src = response.data.images.original.url;
      })
  }
</script>

Now that we have a function that is asynchronous, we can then start refactoring from using promises to using await:

<script>
  const img = document.querySelector('img');

  async function getCats() {
    const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'});
    response.json().then(function(response) {
      img.src = response.data.images.original.url;
    });
  }
</script>

Since response is still the same object we have passed to the .then() block at the start, we still need to use the .json() method, which in turn returns a promise. Because .json() returns a promise, we can use await to assign the response to a variable.

<script>
  const img = document.querySelector('img');

  async function getCats() {
    const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'});
    const catData = await response.json();
    img.src = catData.data.images.original.url;
  }
</script>

To use this function, we just simply need to call it with getCats() in our code.

<script>
  const img = document.querySelector('img');

  async function getCats() {
    const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'});
    const catData = await response.json();
    img.src = catData.data.images.original.url;
  }
  getCats();
</script>

This code will behave exactly like the code from the last lesson, it just looks a bit different after refactoring. async/await are very useful tools when it comes to cleaning up asynchronous javascript code. It is important to remember async/await are just promises written in a different way. Do the assignments below, and dive deeper into the understanding of async/await.

  1. Read this article for a solid introduction to async/await. this article also has some good examples of it’s use.

  2. Watch the next video for a good overview on async/await and it’s purpose, along with a special trick.

  1. If you feel brave enough, read this article for a more in-depth look at async/await, including how to handle errors. (Student note: might be far too advanced for now, since it mentions documents databases and several other backend stuff!)

Advanced Async/Await

When using the async/await pair in a loop, and especially in a loop callback function such as in foreach or `map, things start to get more complicated. Take a long break and read this interesting and important article on JavaScript async and await in loops.

Additional Resources

  1. This video is an example of how you can change callbacks, to promises, to async/await.

  1. This video gives a comprehensive view of Promises, async, and await.

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

UPDATED: 22.05.2021

  • [10.03.2021] Added article on async/await in loops

CONTRIBUTORS:

Working with APIs (v1)

Introduction

One of the most powerful things a web developer can do is fetching data from a server and displaying it creatively on their site. In many cases, the server solely exists for that specific site. The server could contain blog posts, user data, high scores for a game or anything else. In other cases, the server is an open service that serves data to anyone that wants to use it (i.e. weather data or stock prices). In either case, the methods of accessing and then using that data are essentially the same.

APIs

Servers that are created for serving data for external use (in websites or apps) are often referred to as APIs or Application Programming Interfaces.

There are multiple ways of requesting data from an API, but all of them basically do the same thing. For the most part, APIs are accessed through URLs, and the specifics of how to query these URLs changes based on the specific service you are using. For example, the OpenWeatherMap API has several types of data that you can request. To get the current weather in a specific location, you need to request data from this URL:

api.openweathermap.org/data/2.5/weather?q=London,uk

You’ll want to switch out the city for the location you’re requesting. The specifics for using any API are usually documented on the service’s website. Check here for the OpenWeatherMap API documentation.

If you haven’t already, go ahead and paste the weather URL above into your browser…(we’ll wait).

Unless the implementation of that specific API has changed, you probably get an error like this:

{"code":401, "message": "Invalid API key. Please see http://openweathermap.org/faq#error401 for more info."}

This brings us to another point about APIs. In most cases, you have to sign up and get an API key to use them. Obtaining the API key is as simple as signing up on their website and using it is usually as easy as pasting it into the URL:

http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=1111111111

(exactly how to include the key changes from service to service)

Services like the OpenWeatherMap use API keys to track who is requesting the data they serve, and how much data they are requesting. The reason they do this is so that people can’t take advantage of their service. Running servers, especially large ones costs money, and while each current weather request (or whatever) is relatively cheap, if the amount of requests gets too high the cost could be significant. Imagine using that API to create an amazing weather app that gets used all over the world….you could easily have thousands of people accessing that data every minute!

By signing up for a service and getting an API key you are letting the service track how much you are actually using. In many cases services are limited as to how much data they can request for free. With the weather app example, their free plan only allows you to make 60 requests per minute and also limits what types of data you can access (details here if you’re interested). So, if your app became successful, you would probably need to pay for a better account.

Luckily for us, the majority our apps are only going to be used by us and the people that view our portfolios. So we’ll get by just fine with free services.

Once you get a key (try this now if you like!) and waited for its activation (see Do I need to activate my API key?) you can paste the URL into the browser again (including your key of course) and hopefully, you’ll see a proper response:

{
    "coord": {
        "lon": -77.73,
        "lat": 38.77
    },
    "weather": [ {
        "id": 800,
        "main": "Clear",
        "description": "clear sky",
        "icon": "01d"
    } ],
    "base": "stations",
    "main": {
        "temp": 75.74,
        "pressure": 1017,
        "humidity": 57,
        "temp_min": 71.6,
        "temp_max": 78.8
    },
    "visibility": 16093,
    "wind": {
        "speed": 3.87,
        "deg": 291
    },
    "clouds": {
        "all": 1
    },
    "dt": 1504188900,
    "sys": {
        "type": 1,
        "id": 2886,
        "message": 0.0053,
        "country": "US",
        "sunrise": 1504175992,
        "sunset": 1504222878
    },
    "id": 4775660,
    "name": "New Baltimore",
    "cod": 200
}

Fetching Data

So how do we actually get the data from an API into our code?

A couple of years ago the main way to access API data in your code was using an XMLHttpRequest. This function still works in all browsers, but unfortunately, it is not particularly nice to use. The syntax looks something like this:

// Just getting XHR is a mess!
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
  request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
  try {
    request = new ActiveXObject('Msxml2.XMLHTTP');
  }
  catch (e) {
    try {
      request = new ActiveXObject('Microsoft.XMLHTTP');
    }
    catch (e) {}
  }
}

// Open, send.
request.open('GET', 'https://url.com/some/url', true);
request.send(null);

Ouch. That was painful.

Developers, feeling the pain of having to write that stuff out, began writing 3rd party libraries to take care of this and make it much easier to use. Some of the more popular libraries are axios and superagent, both of which have their strengths and weaknesses.

More recently, however, web browsers have begun to implement a new native function for making HTTP requests, and that’s the one we’re going to use and stick with for now. Meet fetch:

// URL (required), options (optional)
fetch('https://url.com/some/url')
  .then(function(response) { 
    // Successful response :)
  })
  .catch(function(err) {
    // Error :(
  });

In case you’ve forgotten, scroll back up and look at how you would use XHR to do the same thing. While you’re admiring how nice and clean that code is, notice the .then() and .catch() functions there. Do you remember what those are? (PROMISES!)

Let’s change up our API for this example. We’re going to walk through an example using fetch with the giphy API to display a random gif on a webpage. The API requires you to sign up and get a free API key, so go ahead and do that here.

Giphy has several methods for searching and finding gifs which you can read about in their documentation. Today we’re just going to use the ‘translate’ endpoint because it’s the simplest one for our purposes. You can find the appropriate URL in their documentation by scrolling down here. What it tells us is that the correct URL is api.giphy.com/v1/gifs/translate and that it requires 2 parameters, your api_key and a search term. If you put it all together correctly (with YOUR API key) you should get something like this:

'https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats'
// of course we're searching for cats

Go ahead and try that URL (with YOUR API key) in a browser. If everything goes well you should get a relatively long string of data and no errors.

CORS

A side note before we start putting this into our code. For security reasons, by default, browsers restrict HTTP requests to outside sources (which is exactly what we’re trying to do here). There’s a very small amount of setup that we need to do to make fetching work. Learning about this is outside our scope right now, but if you want to learn a bit about it this wikipedia article is a decent starting point.

Whether or not you took the detour to learn all about Cross Origin Resource Sharing (CORS) the fix is simple. With fetch, you are able to easily supply a JavaScript object for options. It comes right after the URL as a second parameter to the fetch function:

fetch('url.url.com/api', {
  mode: 'cors'
});

Simply adding the {mode: 'cors'} after the URL, as shown above, will solve our problems for now. In the future, however, you may want to look further into the implications of this restriction.

Let’s Do This

For now, we’re going to keep all of this in a single HTML file. So go ahead and create one with a single blank image tag and an empty script tag in the body.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <img src="#" />
  <script>
  </script>
</body>
</html>

In the script tag, let’s start by selecting the image and assigning it to a variable so that we can change the URL once we’ve received it from the Giphy API.

<script>
  const img = document.querySelector('img');
</script>

Adding fetch with our URL from above is also relatively easy:

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      console.log(response.json());
    });
</script>

You should now be able to open the HTML file in your browser, and while you won’t see anything on the page, you should have something logged in the console. The trickiest part of this whole process is deciphering how to get to the data you desire from the server’s response. In this case, inspecting the browser’s console will reveal that what’s being returned is another Promise… to get the data we need another .then() function.

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      console.log(response);
    });
</script>

Now we have a JavaScript object and if you inspect it closely enough you’ll find that the data we need (an image URL) is nested rather deeply inside the object:

response

To get to the data we need to drill down through the layers of the object until we find what we want!

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      console.log(response.data.images.original.url);
    });
</script>

Running the file should now log the URL of the image. All that’s left to do is set the source of the image that’s on the page to the URL we’ve just accessed:

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      img.src = response.data.images.original.url;
    });
</script>

If all goes well, you should see a new image on the page every time you refresh!

If you’ve gotten lost along the way, check the code below. Besides the glorious styling, this is what your version should look like.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <style>
    body {
      background-color: #e6d8e7;
      display: flex;
      height: 90vh;
      align-items: center;
      justify-content: center;
    }
  </style>
  <img src="#" alt="cat">
  <script>
  const img = document.querySelector('img')
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=bb2006d9d3454578be1a99cfad65913d&s=cat', {mode: 'cors'})
    .then(function(response) {
      return response.json()
    })
    .then(function(response) {
      img.src = response.data.images.original.url
    })
    .catch(e => {
      console.log(e)
    })
</script>
</body>
</html>

Study

  1. Read the fetch documentation here. It’s not all that complicated to use, but we’ve only really scratched the surface at this point. You can also watch the last part of this live session which shows XHR and the Fetch API getting data from the Rest Countries JSON API.

  2. Check out this list of free, open APIs and let your imagination go wild.

  3. Expand on our little project here by adding a button that fetches a new image without refreshing the page.

  4. Add a search box so users can search for specific gifs. You should also investigate adding a .catch() to the end of the promise chain in case Giphy doesn’t find any gifs with the searched keyword. Add a default image, or an error message if the search fails.

CONTRIBUTORS

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

UPDATED: 02.05.2021

Async (v1)

Introduction

Since JavaScript is the language of the web, there are some functions that by necessity are going to take a decent amount of time to complete, such as fetching data from a server to display on your site. For this reason, JavaScript includes support for asynchronous functions, or to put it another way, functions that can happen in the background while the rest of your code executes.

Learning Objectives

  1. What is a callback?
  2. What’s a promise?
  3. What are circumstances when promises are better than callbacks?
  4. What does the .then() function do?

Callbacks

In the recent past, the way that these were most commonly handled were with callbacks, and even now they are still used quite a lot in certain circumstances.

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. MDN

Callbacks are simply functions that get passed into other functions. For example:

myDiv.addEventListener("click", function(){
  // do something!
})

Here, the function addEventListener() takes a callback (the "do something" function) and then calls it when myDiv gets clicked.

You will likely recognize this pattern as something that happens all the time in JavaScript code. Unfortunately, though they are useful in situations like the above example, using callbacks can get out of hand, especially when you need to chain several of them together in a specific order. The rest of this lesson discusses patterns and functions that will help keep you out of Callback hell.

Take a moment to skim through this article before moving on. Or, if you prefer a video watch this.

Promises

There are multiple ways that you can handle asynchronous code in JavaScript, and they all have their use cases. Promises are one such mechanism, and they’re one you will see somewhat often when using other libraries or frameworks. Knowing what they are and how to use them is quite useful.

Essentially, a promise is an object that might produce a value at some point in the future. Here’s an example:

Lets say getData() is a function that fetches some data from a server and returns it as an object that we can use in our code:

const getData = function() {
  // go fetch data from some API...
  // clean it up a bit and return it as an object:
  return data
}

The issue with this example is that it takes some time to fetch the data, but unless we tell our code that, it assumes that everything in the function happens essentially instantly. So, if we try to do this:

const myData = getData()
const pieceOfData = myData['whatever']

We’re going to run into trouble because when we try to extract pieceOfData out of the returned data, the function getData() will most likely still be fetching, so myData will not be the expected data, but will be undefined. Sad.

We need some way to solve this problem, and tell our code to wait until the data is done fetching to continue. Promises solve this issue. We’ll leave learning the specific syntax for the articles you’re about to read, but essentially Promises allow you to do this:

const myData = getData() // if this is refactored to return a Promise...

myData.then(function(data){ // .then() tells it to wait until the promise is resolved
  const pieceOfData = data['whatever'] // and THEN run the function inside
})

Of course there many more occasions where one would want to use Promises beyond fetching data, so learning these things now will be very useful to you.

Study

  1. Read this article. It’s a good starting place and it’s short and to the point.

  2. Watch the next video. It’s a good place to get a feel for how one might actually use promises in the wild. Feel free to watch the other videos in the series, but they aren’t strictly needed at this point. The video also mentions the ES5/ES6 issue, don’t worry about that at this point either. All major browsers support Promises and we will teach you how to support older browsers in a later lesson.

  1. Watch this video to understand how asynchronous code works in JavaScript.

  1. Read Chapter 2: Callbacks and Chapter 3: Promises from You Don't Know JS. In Chapter 2, the author explains the problems with callbacks and why callback hell will be your worst enemy (hint: it’s the inversion of control and non-linear nature of callbacks). In Chapter 3, you go deep into the how and why of promises. This chapter is not the easiest read, but you’ll be a promise professional if you take the time to properly digest it. It’s worth the effort.

Additional Resources

  1. This is another useful article about Callback functions in JavaScript.

  2. The MDN Documentation for Promises. It might not be the best resource for learning all about them, but once you’ve read a more friendly article or tutorial, this will probably be the place you return to for a refresher.

  3. This video and this one too are both nice introductions to Promises if you need more repetition.

  4. This tutorial is another good introduction.

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

UPDATED: 13.01.2021

JSON (v1)

Introduction

JSON (JavaScript Object Notation) is a standardized format for structuring data. It is heavily based on the syntax for JavaScript objects. You will often encounter JSON formatted data when working with external servers or APIs – it is essentially the universal format for transmitting data on the web. Go through the following resources and you’ll be good to go.

Study

  1. This MDN tutorial is probably all you need…

  2. Read about the 2 JavaScript methods that you’ll most often be using when dealing with JSON – JSON.parse() and JSON.stringify().

  3. Mis-formatted JSON is a common cause of errors. This webpage lets you paste in JSON code and will search it for formatting errors.

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

UPDATED: 13.01.2021

Project: Weather App

Introduction

In this project you will create a weather forecast site using the weather API from the previous topic. You should be able to search for a specific location and toggle displaying the data in Fahrenheit or Celsius.

In addition, you should change the look of the page based on the data. You can either change the the color of the background or you can use the Giphy API to find appropriate weather-related gifs and display them.

Feel free to use promises or async/await in your code. However it is important to try to become comfortable with both.

Assignment

  1. Set up a blank HTML document with the appropriate links to your JavaScript and CSS files.

  2. Write the functions that hit the API. You’re going to want functions that can take a location and return the weather data for that location. For now, just console.log() the information.

  3. Write the functions that process the JSON data you’re getting from the API and return an object with only the data you require for your app.

  4. Set up a simple form that will let users input their location and will fetch the weather info (still just console.log() it).

  5. Display the information on your webpage!

  6. Add any styling you like!

  7. Optional: add a ‘loading’ component that displays from the time the form is submitted until the information comes back from the API.

  8. Push your solution to Github and submit the URL in the Quiz below.


The archived old version of this post can be found here

UPDATED: 09.06.2021

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

Async and Await

Introduction

When we have a lot of things going on in our code following the asynchronous code can be tricky. For this reason we have two keywords async and await that help us deal with this problem. These two keywords can help make asynchronous read more like synchronous code. Thus our code looks cleaner while keeping the benefits of asynchronous code.

Let’s see an example. In both cases we have a function that gets some information from a server, processes it, and returns a promise. Both functions do the exact same thing.

function getCountiesInfo(name) {
  return server.getCountries().then(countries => {
    return countries.find(country => { return country.name === name });
  });
}
async function getCountriesInfo(name) {
  const countries = await server.getCountries();
  const country = countries.find(country => { return country.name === name });
  return country;
}

Have you noticed the async keyword before the function declaration? How about the await keyword before server.getCountries()?

Learning Objectives

  1. How we declare an async function
  2. What the async keyword does
  3. What the await keyword does
  4. What is returned from an async function
  5. What happens when an error is thrown inside an async function
  6. How we handle errors inside an async function

The Async Keyword

In order to let javaScript engine know that we are declaring an asynchronous function we need to use the keyword async before that function. Inside that function it is required to use await before the functions. When we are declaring a function with the async, it automatically returns a promise. Returning in an async function is the same as resolving a promise, likewise, throwing an error will reject the promise.

Async functions are just syntactical sugar for promises. The async keyword can also be used with any of the ways a function can be created. In other words, it is valid to use an async function anywhere we can use a normal function.

Now let’s see some examples. It’s ok if you don’t understand them.You can come back and take a look when you have gone through more stuff.

  const myAsyncFunc = async () => {
    // do something asynchronously and return a promise
    return result;
  }
 myArray.forEach(async item => {
   // do something asynchronously for each item in 'myArray'
   // one could also use .map here to return an array of promises to use with 'Promise.all()'
 });
server.getAnimals().then(async animals => {
  animals.forEach(animal => {
    // do something asynchronously for each animal
  });
});

The Await Keyword

The await keyword tells javaScript to wait for an asynchronous action to finish before continuing the function. The await keyword is used to get a value from a function where we would normally use .then(). In other words, instead of calling .then() after the asynchronous function, we would simply assign a variable to the result using await. Then we can use the result in our code as we would in our synchronous code.

Handling Errors

Handling errors in async functions is very easy. As we saw in promises, promises have the .catch() method for handling rejected promises. Since async functions just return a promise, we can simply call the function, and append a .catch() method to the end.

asyncFunctionCall().catch(err => {
  console.error(err)
});

There is also another way that we can handle errors in async functions. We can use the try/catch block just like we would inside synchronous code. Thus we can handle the error directly inside the async function.

async function getCountriesInfo(name) {
  try {
    const countries = await server.getCountries();
    const country = countries.find(country => { return country.name === name });
    return country;
  } catch (error) {
    // Here you can handle the error any way you'd like
  }
}

This way it can look messy, however, it is very easy to handle errors without appending .catch() after your function calls. Keep in mind that the way you handle errors is up to you and which method you use should be determined by how your code was written. Over time you will get more comfortable of what needs to be done.

Time for some practice!!!

Time for Practice

Now we are going to take the Giphy API and convert the promise based code into async/await compatible code.

Here’s a refresher of the code we are starting with:

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      img.src = response.data.images.original.url;
    });
</script>

Await does not work on the global scope. Therefore we will have to create an async function that wraps our API call to Giphy.

<script>
  const img = document.querySelector('img');

  async function getCats() {
    fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
      .then(function(response) {
        return response.json();
      })
      .then(function(response) {
        img.src = response.data.images.original.url;
      })
  }
</script>

Now we have a function that is asynchronous. So we can start refactoring from using promises to using await:

<script>
  const img = document.querySelector('img');

  async function getCats() {
    const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'});
    response.json().then(function(response) {
      img.src = response.data.images.original.url;
    });
  }
</script>

Since response is still the same object we have passed to the .then() block at the start, we still need to use the .json() method, which in turn returns a promise. Since .json() returns a promise, we can use await to assign the response to a variable.

<script>
  const img = document.querySelector('img');

  async function getCats() {
    const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'});
    const catData = await response.json();
    img.src = catData.data.images.original.url;
  }
</script>

Now in order to use this function, we need to call it with getCats() in our code.

<script>
  const img = document.querySelector('img');

  async function getCats() {
    const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'});
    const catData = await response.json();
    img.src = catData.data.images.original.url;
  }
  getCats();
</script>

Although this code looks a bit different after refactoring, it will behave exactly the same as in the previous topic. When it comes to cleaning up asynchronous javascript code, async/await are very useful tools. Keep in mind that async/await are just promises written in a different way.

Study

Now let’s dive deeper into the understanding of async/await.

  1. Read this article for a solid introduction to async/await. Also this article has some good examples of it’s use.

  2. Watch the next video for a good overview on async/await and it’s purpose, along with a special trick.

  1. If you feel brave enough, read this article for a more in-depth look at async/await, including how to handle errors. (Student note: might be far too advanced for now, since it mentions documents databases and several other backend stuff!)

Advanced Async/Await

When using the async/await pair in a loop, and especially in a loop callback function such as in foreach or `map, things start to get more complicated. Take a long break and read this interesting and important article on JavaScript async and await in loops.

Additional Resources

In this section you can find a lot of helpful links to other content. This is a supplemental material for you if you want to dive deeper into some concepts.

  1. The following video is an example of how you can change callbacks, to promises, to async/await.

  1. The following video gives a comprehensive view of promises, async, and await.


The archived old version of this post can be found here

UPDATED: 22.05.2021

  • [10.03.2021] Added article on async/await in loops

CONTRIBUTORS:

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

Working with APIs

Introduction

As a web developer you will have to do several tasks. One of the most important and powerful task is to fetch data from a server and creatively display them on the site. The server can contain several things, such as blog posts, user data, high scores etc. Furthermore in other cases the server is an open service that serves data to anyone that wants to use it. The methods that we access and use the data is the same no matter the case.

Introduction to APIs

APIs or Application Programming Interfaces are servers that are created for serving data for external use. Let’s see a short video of what an API is.

There are several ways of requesting data from an API. However all of them basically do the same thing. APIs are accessed through URLs, and the specifics of how to query these URLs changes based on the specific service we are using.

Let’s see how we can fetch data from the OpenWeatherMap API. The OpenWeatherMap API has several types of data that we can request. In order to get the current weather in a specific location, we need to request data from this URL:

api.openweathermap.org/data/2.5/weather?q=London,uk

This url returns some information for the London in UK. If we want to search for a different city, then we need to switch out the city for the location we want. The specifics for using any API are usually documented on the service’s website. Check here for the OpenWeatherMap API documentation.

Now go ahead and paste the weather URL above into your browser. You will probably get the following an error, unless the implementation of that specific API has changed.

{"code":401, "message": "Invalid API key. Please see http://openweathermap.org/faq#error401 for more info."}

This is another key factor about APIs. In most cases, we have to sign up and get an API key to use them. Don’t worry though because the procedure is simple. To obtain the API key we sign up on their website and we use it by pasting it into the URL like this:

http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=1111111111

(exactly how to include the key changes from service to service)

The reason that services like the OpenWeatherMap use API keys is that they want to track who is requesting the data they serve, and how much data they are requesting. This is due to the fact that they don’t want people to take advantage of their service.

Running large servers costs money. In addition although each weather request is relatively cheap, if the amount if requests gets too high the cost could be significant. If for example you have built a weather app that gets used by people from all over the world, you can have thousands of requests every minute.

Therefore, when we sign up for a service and get an API key, we are letting the service track how much we are actually using. In many cases services are limited as to how much data users can request for free. For example the free plan of the OpenWeatherMap service allows us only to make 60 requests per minute and also limits what types of data we can access. If you are interested you can find more details here.

For the majority of our apps it is fine to use the free service, since our apps will be used by us and the people that view our portfolios.

Once you get a key (try this now if you like!) and waited for its activation (see Do I need to activate my API key?) you can paste the URL into the browser again (including your key of course) and hopefully, you’ll see a proper response:

{
    "coord": {
        "lon": -77.73,
        "lat": 38.77
    },
    "weather": [ {
        "id": 800,
        "main": "Clear",
        "description": "clear sky",
        "icon": "01d"
    } ],
    "base": "stations",
    "main": {
        "temp": 75.74,
        "pressure": 1017,
        "humidity": 57,
        "temp_min": 71.6,
        "temp_max": 78.8
    },
    "visibility": 16093,
    "wind": {
        "speed": 3.87,
        "deg": 291
    },
    "clouds": {
        "all": 1
    },
    "dt": 1504188900,
    "sys": {
        "type": 1,
        "id": 2886,
        "message": 0.0053,
        "country": "US",
        "sunrise": 1504175992,
        "sunset": 1504222878
    },
    "id": 4775660,
    "name": "New Baltimore",
    "cod": 200
}

Access API Data

So the question is. How do we actually get the data from an API into our code?

A few years ago the main way to access API data in your code was using an XMLHttpRequest. Although this function still works in all browsers, it is not nice to use.

The syntax looks something like this:

// Just getting XHR is a mess!
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
  request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
  try {
    request = new ActiveXObject('Msxml2.XMLHTTP');
  }
  catch (e) {
    try {
      request = new ActiveXObject('Microsoft.XMLHTTP');
    }
    catch (e) {}
  }
}

// Open, send.
request.open('GET', 'https://url.com/more/url', true);
request.send(null);

Ouch. That wasn’t simple at all!!!

For this reason developers have begun writing 3rd party libraries to take care of this and make it much easier to use. Some of the more popular libraries are axios and superagent, both of which have their strengths and weaknesses.

However, more recently, web browsers have begun to implement a new native function for making HTTP requests. This function is fetch() and it is the one that we are going to be using and stick for now.

// URL (required), options (optional)
fetch('https://url.com/more/url')
  .then(function(response) { 
    // Successful response :)
  })
  .catch(function(err) {
    // Error :(
  });

Now, scroll back up and look at how you would use XHR to do the same thing. See how nice and clean this code is? Also notice the .then() and .catch() functions. What those are? (PROMISES!)

Now we will see an example using fetch with the giphy API. With this API we will display a random gif on a webpage. The API requires you to sign up and get a free API key. So go ahead and do that here. Giphy has several methods for searching and finding gifs. You can find all about it in their documentation.

In our example we are going to use the ‘translate’ endpoint because it’s the simplest one for our purposes. You can find the appropriate URL in their documentation by scrolling down here. What it tells us is that the correct URL is api.giphy.com/v1/gifs/translate and that it requires 2 parameters, your api_key and a search term.

So if we put it all together and let’s say we are searching for cats then the url that we will get should be something like this:

'https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats'

Now let’s try that URL (with YOUR API key) in a browser. If everything goes well you should get a relatively long string of data and no errors.

Introduction to CORS

Before we start and put all this stuff into our code let’s make a side note. For security reasons, by default, browsers restrict HTTP requests to outside sources. Therefore there is a small amount of setup that we need to do to make fetching work.

Having said that learning about this is outside our scope right now, but if you want to learn a bit about it this you can check out this wikipedia article.

Whether or not you learned all about Cross Origin Resource Sharing (CORS) the fix is simple. By using fetch, you are able to easily supply a JavaScript object for options. To be more specific, it comes right after the URL as a second parameter to the fetch function:

fetch('url.some.com/api', {
  mode: 'cors'
});

So what we need to do is to simply add the {mode: 'cors'} after the URL. For now this will work, but in the future you need to look further into the implications of this restriction.

Time for Practice

For now, we’re going to keep all of this in a single HTML file. So

  1. Create an HTML file
  2. In the body add a single blank image tag
  3. In the body ddd an empty script tag
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <img src="#" />
  <script>
  </script>
</body>
</html>

Now inside the script tag, we will select the image and assign it to a variable. In that way we can change the URL once we’ve received it from the Giphy API.

<script>
  const myImg = document.querySelector('img');
</script>

Now we will add the fetch with our URL.

<script>
  const myImg = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      console.log(response.json());
    });
</script>

Now open the HTML file in your browser. You won’t be able to see anything on the page, however you should have something logged in the console.

The trickiest part is how to get to the data you desire from the server’s response. So if we inspect the browser’s console will reveal that what’s being returned is another promise. So in order to get the data we need another .then() function.

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      console.log(response);
    });
</script>

Now we have a JavaScript object. If you inspect it in the console closely enough you’ll find that the data we need (an image URL) is nested rather deeply inside the object:

response

Therefore, in order to get to the data we need to drill down through the layers of the object until we find what we want!

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      console.log(response.data.images.original.url);
    });
</script>

Running the file should now log the URL of the image. Finally we need to set the source of the image that’s on the page to the URL we’ve just accessed:

<script>
  const img = document.querySelector('img');
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=YOUR_KEY_HERE&s=cats', {mode: 'cors'})
    .then(function(response) {
      return response.json();
    })
    .then(function(response) {
      img.src = response.data.images.original.url;
    });
</script>

You should now be able to see a new image on the page every time you refresh!

If you’ve gotten lost along the way, check the code below. Besides the glorious styling, this is what your version should look like.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <style>
    body {
      background-color: #e6d8e7;
      display: flex;
      height: 90vh;
      align-items: center;
      justify-content: center;
    }
  </style>
  <img src="#" alt="cat">
  <script>
  const img = document.querySelector('img')
  fetch('https://api.giphy.com/v1/gifs/translate?api_key=bb2006d9d3454578be1a99cfad65913d&s=cat', {mode: 'cors'})
    .then(function(response) {
      return response.json()
    })
    .then(function(response) {
      img.src = response.data.images.original.url
    })
    .catch(e => {
      console.log(e)
    })
</script>
</body>
</html>

Study

  1. Read the fetch documentation here. You can also watch the last part of this live session which shows XHR and the Fetch API getting data from the Rest Countries JSON API.

  2. Check out this list of free, open APIs and let your imagination go wild.

  3. Expand on our little project here by adding a button that fetches a new image without refreshing the page.

  4. Add a search box so users can search for specific gifs. You should also investigate adding a .catch() to the end of the promise chain in case Giphy doesn’t find any gifs with the searched keyword. Add a default image, or an error message if the search fails.


The archived old version of this post can be found here

UPDATED: 09.06.2021

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

Async

Introduction

There are some functions in JavaScript that take a decent amount of time to complete. This is due to the fact that JavaScript is the language of the web and thus some operations such as fetching data from a server might take some time to complete.

These functions are called asynchronous functions, that is functions that happen in the background while the rest of the code executes. Likely JavaScript includes support for those functions.

Learning Objectives

  1. What a callback is
  2. What a promise is
  3. When promises are better than callbacks
  4. What the .then() function does

Introduction to Callbacks

Until recently the asynchronous functions were handled with callbacks. In certain circumstances callbacks are still used quite a lot. But what is a callback?

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. MDN

So, basically callbacks are functions that get passed into other functions. Let’s see an example.

myElement.addEventListener("click", function(){
  // do something here!
})

In this example, the function addEventListener() takes a callback (the "do something here" function) and then calls it when myElement gets clicked.

This pattern is something that you should be familiar with in JavaScript code. Although we can use the example above in several situations there are other situations where using callbacks can be tricky. For example if we have to chain several callback functions together in a specific order.

Therefore in the rest of this topic we will see patterns and functions that will help you to get out of this Callback hell. So skim through this article before moving on. If you prefer a video instead take a look at this.

Introduction to Promises

Although there are multiple ways that we can handle asynchronous code in JavaScript, Promises is the most common used when using other libraries or frameworks. It is very useful to know what they are and how we can use them.

Basically a promise is an object that might produce a value at some point in the future.

Let’s see an example. We have a function called fetchData() that fetched data from a server. This function returns these data as an object that we can use in our code.

const fetchData = function() {
  // fetch data from an API
  // clean it up a bit and return it as an object:
  return data
}

The problem here is that the function fetchData() takes some time to fetch the data. Thus, if we don’t tell that to our code it will assume that everything happens instantly.

So if we try to do the following:

const myData = fetchData()
const someData = myData['do something here']

We will have problems. When we try to extract someData out of the returned data, the function fetchData() will most likely still be fetching. Therefore the myData will not be the expected data, but instead it will be undefined.

So we need somehow to tell our code to wait until the data is done fetching in order to continue. Promises solve these kind of problems. Basically promises allow us to do the following thing:

const myData = fetchData() // if this is refactored to return a Promise...

myData.then(function(data){ // the .then() tells it to wait until the promise is resolved
  const someData = myData['do something here'] // and THEN run the function inside
})

Promises are also used in many other cases beyond fetching data. Thus it is really useful to learn now those things.

Study

  1. A good starting place is this article. It’s a short article and to the point.

  2. Watch the next video. The other videos in the series aren’t needed at this point, but feel free to watch them if you want to. The video also mentions the ES5/ES6 issue, don’t worry about that either. All major browsers support Promises and we will teach you how to support older browsers in a later lesson.

  1. Watch the next video to understand how asynchronous code works in JavaScript.

  1. Read Chapter 2: Callbacks and Chapter 3: Promises from You Don't Know JS. In Chapter 2, the author explains the problems with callbacks and why callback hell will be your worst enemy. In Chapter 3, you go deep into the how and why of promises. This chapter is not the easiest read, but you’ll be a promise professional if you take the time to properly digest it. It’s worth the effort.

Additional Resources

In this section you can find a lot of helpful links to other content. This is a supplemental material for you if you want to dive deeper into some concepts.

  1. Another useful article about Callback functions in JavaScript is this.

  2. The MDN Documentation for Promises. It might not be the best resource for learning all about them, but once you’ve read a more friendly article or tutorial, this will probably be the place you return to for a refresher.

  3. If you need more repetition to promises this video and this one too are both really nice introductions.

  4. Another good introduction is this tutorial.


The archived old version of this post can be found here

UPDATED: 09.06.2021

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.

JSON

Introduction

JSON (JavaScript Object Notation) is a standardized format for structuring data. This format is heavily based on the syntax for JavaScript objects. When working with external servers or APIs the data that you would be receiving are most likely to be in that format. JSON is essentially the universal format for transmitting data on the web.

Go through the following resources and you will be in a good shape.

Study

  1. This MDN tutorial is really all what you need.

  2. Go through JSON.parse() and JSON.stringify(). These are the two most used JavaScript methods.

  3. A common cause of errors is the mis-formatted JSON. This webpage lets you paste in JSON code and will search it for formatting errors.

Additional Resources


The archived old version of this post can be found here

UPDATED: 09.06.2021

Feedback

  • Is there anything we can help with up to this point? Do you have something to suggest about this chapter? Let us know in the comments below.