December 09, 2017
javascriptI built the same program 4 different ways. I started with callbacks, moved on to Promises, used generators, and finished up with async/await.
The program:
Makes a request to Github’s users endpoint
Pulls back my Github profile
Logs the response
Here’s what I came up with.
I struggled to make an HTTP request using callbacks. I’ve mostly used Promises to write asynchronous JavaScript. I generally use axios or fetch in my applications, which are both Promise-based.
I ended up having to turn to XMLHTTPRequest for this version of the application, which I’ve never used before!
const makeHTTPRequest = (url, methodType, callback) => {
const xhr = new XMLHttpRequest();
xhr.open(methodType, url, true);
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
callback(xhr.responseText);
}
};
xhr.send();
};
const getLogin = (response) => {
console.log(JSON.parse(response));
};
const url = "https://api.github.com/users/maecapozzi";
makeHTTPRequest(url, "GET", getLogin);
I’ll walk you through what this code does:
I define a function called makeHTTPRequest
. It’s designed to actually make the request to Github.
I pass three methods to makeHTTPRequest
, url
, methodType
, and callback
. url
is the endpoint I want to hit. methodType
is the HTTP method I want to use. And callback
is the function I want to call when I actually get a response back from Github.
I define a function called getLogin
and pass it response as an argument. The function takes the response I receive from Github, and parses it to JSON. Then, it logs the parsed response.
I pass getLogin
into makeHTTPRequest
as callback. That means getLogin
will take the response from Github has it’s argument.
After achieving my goals with callbacks, I attempted with promises. This felt straightforward, since I’ve done it many times before.
const makeHTTPRequest = (username) => {
const url = "https://api.github.com/users/" + username;
fetch(url)
.then((response) => response.json())
.then((response) => console.log(response));
};
makeHTTPRequest("maecapozzi");
I defined a function called makeHTTPRequest
and passed it a username
.
I used fetch
to make a request to Github.
I use .then()
to wait for the request to Github to complete, and then convert the response to JSON.
I log the response
This was my first foray into generators. The syntax and concept were totally foreign to me upon approaching this challenge.
function* getUser(username) {
const uri = "https://api.github.com/users/" + username;
const response = yield fetch(uri);
const parsedResponse = yield response.json();
console.log(parsedResponse);
}
getUser("maecapozzi");
I define getUser
and say that it’s a generator by using the *
syntax. I pass in username as an argument.
I create a variable called response
and set it equal to response I receive from Github after making an HTTP request using fetch
. The important piece of line 3 is that I use the keyword yield
. yield
is telling my program that I do want to set response equal to the response I get back from Github, but only after the request is completed.
I follow the same pattern again when I set parsedResponse
equal to response.json(
). I have to wait for the Promise to resolve before I can set my variable. If I don’t use yield
, when I try to log parsedResponse
, I get: Promise {<pending>}
back.
Finally, I wrote the application once more using ES7 async/await. Since I did this after building the same application with generators, it became really obvious how async/await is built on top of generators.
const getUser = async (username) => {
const uri = "https://api.github.com/users/" + username;
const response = await fetch(uri);
const parsedResponse = await response.json();
console.log(parsedResponse);
};
getUser("maecapozzi");
I define an async function called getUser that takes username as an argument.
I created a variable called response
and set it equal to the response I receive from Github after making a request to the /users/:id
endpoint. The key is that I use the await
keyword to tell my program to wait for the request to resolve itself before setting response equal to the response I get back.
I use the same pattern again on line 4.
Then I log the parsed response.
This was a worthy endeavor for a few reasons. First of all, I hadn’t used callbacks much, so I didn’t really know how big of a deal Promises were. I also had been taking fetch and axios for granted, since they made making HTTP requests so much more straightforward.
I also had never used generators or async/await. Although I found async/await much easier to use than generators, it was helpful to see how async/await was built on top of generators. It was also fun to get my hands dirty with some ES7 syntax.
If you liked this post, please consider sharing it!
Sign up for the Design Systems Newsletter today!