(https://hexlet.io/courses/http_protocol) (https://hexlet.io/courses/http-api)
Using a DOM tree does help make our sites more lively. But it is still not enough to create standalone widgets or full-fledged Single Page Application (SPA) with a backend.
Let s take a specific example. Many services allow using different widgets, such as weather or currency rates. It works like this: you receive some code from a service and insert it into your HTML. Next, this code loads the widget itself and periodically requests the necessary data from the service servers.
It can happen whenever the widget user clicks buttons that require new data, such as to show the weather for the next week.
We use a similar widget on Hexlet; you can see it in the lower-right corner of every page. It lets you search through our guide and message our support. The widget does not interact with the backend of Hexlet because it works using a separate service.
The key technology here is a mechanism for executing HTTP requests directly from the browser. We call it AJAX, which stands for Asynchronous JavaScript and XML. Despite the name, this technology works with other things, not just XML.
XMLHttpRequest
Before the html5, browsers provided an XMLHttpRequest
object:
// The example of a typical request using XMLHttpRequest
// Just for reference
const request = new XMLHttpRequest();
request.onreadystatechange = () => {
if (request.readyState == 4 && request.status == 200) {
document.getElementById('demo').innerHTML = request.responseText;
}
};
request.open('GET', '/api/v1/articles/152.json', true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.send();
It's inconvenient, so everyone uses a wrapper from the jQuery library. There'll be more about this in our lesson dedicated to jQuery.
Fetch
With the HTML5 standard, a new mechanism for HTTP requests appeared:
// The example of a typical query using fetch
// const promise = fetch(url[, options]);
fetch('/api/v1/articles/152.json')
.then((response) => {
console.log(response.status); // => 200
console.log(response.headers.get('Content-Type'));
return response.json();
})
.then((article) => {
console.log(article.title); // => 'How do I use fetch?'
})
.catch(console.error);
As you can see, fetch
is a function that returns a promise. It's convenient and pleasant to work with it. And thanks to the existence of polyfills, you don't have to worry about a browser not supporting this mechanism.
Note that response.json
also returns a promise. In addition to json
, data can be obtained using the blob
, text
, formData
, and arrayBuffer
functions.
Sending a form with a POST request:
const form = document.querySelector('form');
fetch('/users', {
method: 'POST',
body: new FormData(form),
});
Sending the form as JSON:
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Hubot',
login: 'hubot',
})
})
For all its advantages, fetch
is a low-level mechanism. For example, when working with JSON, you'll have to set headers manually and do various things with data that otherwise could be automated.
That's why programmers created several libraries that work similarly but provide many more features. Moreover, many of these libraries are isomorphic, so they work the same way both in the browser and on the server. One of the most popular libraries is axios.
URL
As we know from previous courses, gluing lines to work with paths or URLs is not a great idea. You can easily make a mistake and end up doing work that a machine can do.
You can always use many third-party libraries or browsers' built-in mechanisms for it, or polyfills for older browsers:
const url = new URL('../cats', 'http://www.example.com/dogs');
console.log(url.hostname); // => www.example.com
console.log(url.pathname); // => /cats
url.hash = 'tabby';
console.log(url.href); // => http://www.example.com/cats#tabby
url.pathname = 'démonstration.html';
console.log(url.href); // => http://www.example.com/d%C3%A9monstration.html
What's nice is that fetch
can work with the URL
object directly:
const response = await fetch(new URL('http://www.example.com/démonstration.html'));
And here's how you can work with query parameters:
// https://some.site/?id=123
const parsedUrl = new URL(window.location.href);
console.log(parsedUrl.searchParams.get('id')); // => 123
parsedUrl.searchParams.append('key', 'value')
console.log(parsedUrl); // => https://some.site/?id=123&key=value
HTTP access control (CORS)
Attackers can use client HTTP requests to steal data. Therefore, browsers control where and how requests are made. You can read more about this mechanism here.
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.