Register to get access to free programming courses with interactive exercises


( (

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.


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;
};'GET', '/api/v1/articles/152.json', true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

It's inconvenient, so everyone uses a wrapper from the jQuery library. There'll be more about this in our lesson dedicated to jQuery.


With the HTML5 standard, a new mechanism for HTTP requests appeared:

// The example of a typical query using fetch
// const promise = fetch(url[, options]);
  .then((response) => {
    console.log(response.status); // => 200
    return response.json();
  .then((article) => {
    console.log(article.title); // => 'How do I use fetch?'

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.


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', '');
console.log(url.hostname); // =>
console.log(url.pathname); // => /cats

url.hash = 'tabby';
console.log(url.href); // =>

url.pathname = 'démonstration.html';
console.log(url.href); // =>

What's nice is that fetch can work with the URL object directly:

const response = await fetch(new URL('émonstration.html'));

And here's how you can work with query parameters:

const parsedUrl = new URL(window.location.href);
console.log(parsedUrl.searchParams.get('id')); // => 123
parsedUrl.searchParams.append('key', 'value')
console.log(parsedUrl); // =>

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.

Hexlet Experts

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

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.

Get access
hours of theory

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing:">Bookmate</span>
<span class="translation_missing" title="translation missing:">Healthsamurai</span>
<span class="translation_missing" title="translation missing:">Dualboot</span>
<span class="translation_missing" title="translation missing:">Abbyy</span>
Suggested learning programs
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.