From jQuery to XMLHttp Request, from Fetch API to Axios, from REST to GraphQL…
London & Lisbon
Once upon a time there lived a good developer. But she was very junior. She used to only use jQuery to make HTTP request in Javascript.
One day while she was searching for a API to practice, her old good friend jQuery not seem to be working. She said to herself, “Oh my God. If I don’t have my jQuery, I can’t make HTTP request and then I will not be able to earn any money?” She was crying because she was sad.
At that time, the god of Javascript appeared and asked “Why are you sad?”
“ I am a developer, and when I was making API calls, my jQuery is not working. If I don’t have my jQuery, I won’t be able to earn any money” she answered.
“I am willing to bring you your HTTP request.” said the god of Javascript. The god soon appeared with Fetch API. He asked, “Is this your tool to make the call?” ”No it isn’t.” she answered.
The god disappeared again. He came back with a XMLHttpRequest.
He asked, “Is this XMLHttpRequest yours?”
The developer answered, “No it isn’t.”
He asked, “Then is this old jQuery yours?”
The developer answered, ”Yes. It’s mine.”
The God of the Javascript said with a smile, “You are very honest. I will give you all three tools as a reward. ”The God gave her all three tools to make HTTP request. The God also gave her an extra bonus of GraphQL and encouraged her to start exploration on top of REST APIs. The developer lived happily ever after
The 10th week at Makers was essentially a lovely holiday spanning 14 days, a temporary break before the final project. In the interim, I planned to practice HTTP request (async API calls) in Javascript.
So here are a debrief of this 14 days.
- Learn about basics of Promise
- Practice to make HTTP request in jQuery/Fetch API/XMLHttp Request
- Start to explore GraphQL
So let’s start about the basics. The reason to learn about Promise is because I found it hard to handle callback when I do series (≥2) of jQuery ajax calls where one call is dependent on previous call. I know there’s Deferrable in jQuery which can mimic Promise, but after reading the syntax, it just not seem to be very easy to operate.
So what is promise? According to this blog (unbelievable early back in 2012),Promise is an object which is returned by the async function like ajax. Promise object has three states
- pending :- means the async operation is going on.
- resovled :- async operation is completed successfully.
- rejected :- async operation is completed with error.
As the previous linked blog explains, the core benefits of promise is not just about aggregating callbacks, but to have a few of the biggest benefits of synchronous functions in async code:
- function composition: chainable async invocations
- error bubbling: for example if at some point of the async chain of invocation an exception is produced, then the exception bypasses all further invocations until a catch clause can handle it.
When I first read about promise, it is just a concept in my head. It only start to make sense when I use a promise-based tool to ajax call (Yes I mean Fetch API) and the world become clear to me.
But before jumping into the lovely Fetch API, I tried to use the “ancient” XMLHttp Request for a bit, as I understand this is the core object that hides behind all the fancy wrappers like jQuery and Fetch API in making the Ajax call. Essentially it is an object that permits a web page to make a request to a server and get a response back without reloading the entire page.
A typical post request in XMLHttp Request can look like this:
var xhr = new XMLHttpRequest();
xhr.open("POST", '/submit', true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200)
{
// Request finished. Do processing here.
}
}
xhr.send("name=Elfi");
As you can see there might be some repetitive code in each request you execute. Furthermore, in order to implement more complicated scenarios like with promise, you need to use a number of built-in options which can be bewildering. So here come Ajax wrapper, , e.g. the jQuery.ajax()
method.
// jQuery Ajax
$.ajax('http://domain/service')
.done(data => console.log(data))
.fail((xhr, status) => console.log('error:', status));
There’s nothing wrong with jQuery, and in Makers it’s the official library I learn to make ajax call. Obviously, the greatest advantage of jQuery is its simplicity. Even I didn’t experience this myself, but it seems to be incredibly flexible because jQuery allows users to add plug-ins. The cons? For myself, if in a web application like mine, and I’m only use jQuery to make only a few requests, then It is not at all bandwidth friendly thinking its 84kb weight. Also, with Promises, you need to wrap jQuery in something like below: var jQueryPromise = $.ajax('/data.json'); var realPromise = Promise.resolve(jQueryPromise).
I hope the argument above could help justify why I so want to try an alternative library to jQuery, and that is Fetch API.
So what about it? At the first glimpse, it is just another jQuery, but:
- The generic Headers, Request, and Response options provide consistency
- Promises can be chained easily, and
- With async/await you don’t need explicit callbacks.
A typical Get request in Fetch API can be something like below. Notice the then
keyword as it indicates a promise returned, and the catch clause in the end for error bubbling.
fetch('https://www.example.com', {
method: 'get'
})
.then(response => response.json())
.then(jsonData => console.log(jsonData))
.catch(err => {
//error block
}
So a final review of Fetch API. Obviously it’s super flexible and easy to use. The callback hell is avoided by Promises. It is supported by all modern browsers. However, after reading some blogs I found that it isn’t a cure to all Ajax call. For example it doens’t send cookie by default and CORS is disabled by default.
As a side note, I also have a look at the popular Axios
as an alternative to Fetch API.
As another Promise-based HTTP client, Axios seems to be working in both browser and in a node.js environment(no comment on this). It also can set or cancel a request or set a response timeout, which as far as I know Fetch cannot do.
A typical Get request in Axios looks like below.
axios.get('/get-user', {
params: {
ID: 1
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
Since I know I will have a closer look at it in my final project (as I plan to try a MERN stack using Axios with React at the frontend), I’m happy to bypass it for now.
And finally, GraphQL.
How I came across GraphQL is a normal story which I believe all developers would have experienced.
I was googling “different ways to make javascript Http request”, “differences about jQuery and Axios”, “Pros and Cons about XMLHttp Request”, when suddenly I saw something like “Forget about REST API, embrace GraphQL”.
— Boom!
Along the career lifespan as a developer, I would say this is a common scenarios where you find out something new and exciting while catching up with some old but matured technologies, and you are struggling with time allocation.
So obviously my plan this week is to practice about the RESTful way to make API call, but I still would like to share my bits and pieces of learning note on GraphQL as I would definitely come back on this in the near future.
So why GraphQL? Over the past decade, REST has become the standard for designing web APIs. However, REST APIs have shown to be too inflexible to keep up with the rapidly changing requirements of the clients that access them. And GraphQL was developed to solve the pain points.
For one, one of the most common problems with REST is over- and under-fetching. Because with REST, the only way for a client to fetch data is by hitting endpoints that return fixed data structures. It’s very difficult to twist the API in a way that it’s able to match clients with their exact data needs.
Over-fetching:
Over-fetching means that a client fetch more information than needed in a fetch. Imagine a server has a database with all users, and a client needs to get all their names. The client might hit an endpoint like /users
to retrieve all the users from the server database. But the response might contain more info other than just names, e.g. BOD, age, gender, etc. This formation that is useless for the client because it only needs to display the users’ names.
Under-fetching:
Under-fetching generally means that one specific endpoint doesn’t provide enough of the required information. The client will have to make additional requests to fetch everything it needs. For example, consider the same client would also need to display the latest post per user. The client would need to make one request to the /users
endpoint and then hit /users/user_id/posts
to get the latest post from each user.
Comparing to having multiple endpoints that return fixed data structures, GraphQL APIs typically only has one single endpoint. This works because the structure of the data that’s returned is not fixed as the client needs to send a customised query
to get the information every time.
For me, to understand how this works isn’t too difficult, as GraphQL really reminds me of SQL. And a query in GraphQL looks just like a query in PostSQL.
For example, for a query to request all the users’ name I listed in the “overfetching” section, it may look like this:
{allPersons {name}}
And to get all the posts title belong to users, a query can look like this:
{ allPersons {posts { title}}}
Simple and clear!
I found that it is much easier to learn a new concept by referring to some old concepts that I’m familiar with (GraphQL vs SQL). And obviously I’m not in a position to say I know GraphQL well enough. But I’m planning to build a small project using it in the next couple of weeks.
Overall, I feel quite happy about my learning path over the Christmas. The city-explorer
app I built using 3 different HTTP request tool definitely helped me to deepen the understanding on Ajax calls. And the more I make, the greedier I become. But just as the fable at the beginning of the blog illustrates, don’t be too greedy in learning or you won’t have time to digest it.
The only missing part about this week is I immersed myself into learning new concepts so much so I totally forgot about testing!
Well, I did use Postman to do some manual tests, but without automatic API test, how could you claim to be a proper JS developer? I would come back sometime on this to finish my uncompleted task…
A very late merry Christmas to you all, and i will see you in the final project week!