тк 3 июля праздник (в беларуси), буду не онлайн (по возможности буду отвечать)

Основы работы с fetch

Сейчас мы с вам начнем изучать работу с методом fetch. Для этого вам необходим браузер и какой-нибудь web сервер: это может быть PHP, либо NodeJS, либо что-то другое - не имеет значения.

В нашем случае важно, чтобы при обращении на определенные URL ваш сервер отдавал в браузер HTML страницы.

Для начала нам нужны две страницы: страница client, части которой мы будем обновлять через AJAX, и страница ajax, содержимое которой мы будем получать через AJAX.

Пусть страница client будет доступна по адресу /client/, а страница ajax - по адресу /ajax/.

Пусть на странице client будет расположен div и кнопка:

<!DOCTYPE html> <html> <head> <title>Тайтл страницы</title> </head> <body> <div id="result"></div> <input type="submit" id="button"> </body> </html>

А на странице ajax - три абзаца:

<p>1</p> <p>2</p> <p>3</p>

Обратите внимание на то, что страница client содержит всю необходимую структуру HTML, а страница ajax - нет.

Все дело в том, что страница client будет загружена в браузер и видима пользователю, а страница ajax будет подгружаться как кусочек HTML кода в какое-то место другой страницы, поэтому теги html, head, body здесь будут лишними.

В дальнейшем я для краткости буду опускать всю структуру страницы client, но эта структура должна быть, имейте ввиду.

Выполняем AJAX запросы

Итак, на странице client у нас есть кнопка и div. Давайте сделаем так, чтобы по нажатию на кнопку через AJAX загрузилось содержимое страницы ajax и отобразилось в теге нашем div.

Начнем с навешивания события на кнопку:

<div id="result"></div> <input type="submit" id="button"> let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { // выполним AJAX запрос });

Для выполнения AJAX запроса используется функция fetch. У нее есть только один обязательный параметр - адрес страницы, содержимое которой мы хотим получить.

Например, для получения страницы по адресу /ajax/ необходимо написать вот так: fetch('/ajax/'). Вот полный код:

<div id="result"></div> <input type="submit" id="button"> let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { fetch('/ajax/'); // выполняем AJAX запрос });

Итак, в нашем коде fetch('/ajax/') получает содержимое страницы /ajax/. Логично, что своим результатом функция fetch должна вернуть текст запрошенной страницы.

На самом деле это не совсем так. Дело в том, что после вызова fetch проходит некоторое время, прежде, чем будет получен ответ сервера. При этом JavaScript код, который расположен ниже функции fetch продолжит выполняться.

То есть мы имеем дело с асинхронным кодом. Это значит, что после вызова fetch весь остальной JavaScript код продолжит свое выполнение, а результат вызова fetch будет доступен только после загрузки запрошенной страницы.

Поэтому fetch возвращает не текст запрошенной страницы, а промис:

<div id="result"></div> <input type="submit" id="button"> let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); // результатом будет промис });

Чтобы получить данные из промиса, мы должны вызвать метод then, передав ему параметром анонимную функцию:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( function() { } ); });

При этом ответ сервера автоматически попадет в первый параметр нашей функции. Давайте назовем этот параметр response:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( function(response) { // Ответ сервера лежит в переменной response } ); });

Переделаем наш код на более "взрослый" - вместо обычной функции для краткости напишем стрелочную:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( response => { } ); });

Итак, как я уже говорил, наша переменная response содержит ответ сервера. На самом деле в нашей переменной содержится достаточно сложный объект класса Response:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( response => { console.log(response); // объект класса Response } ); });

Глубоко этот объект мы будем изучать в следующих уроках, а пока нам нужно самое простое - получить текст запрошенной страницы. Для этого в объекте response существует метод text.

То есть текст страницы можно получить так: response.text(). Однако, на самом деле это будет еще не текст, как кажется с первого взгляда, а снова промис:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( response => { console.log(response.text()); // выведет Promise } ); });

Чтобы добраться до текста страницы, необходимо промис, полученный из response.text(), обработать еще раз:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( response => { return response.text(); } ).then( text => { // В переменную text попадет текст страницы } ); });

Итак, мы наконец получили текст запрошенной страницы и можем, например, записать его в наш див:

let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( response => { return response.text(); } ).then( text => { result.innerHTML = text; } ); });

Давайте соберем весь наш код вместе:

<div id="result"></div> <input type="submit" id="button"> let result = document.getElementById('result'); let button = document.getElementById('button'); button.addEventListener('click', function() { let promise = fetch('/ajax/'); promise.then( response => { return response.text(); } ).then( text => { result.innerHTML = text; } ); });

Если запустить приведенный код и нажать на кнопку, что через некоторое время (на локальном компьютере оно очень маленькое) в див загрузится содержимое страницы /ajax/.

Дан абзац и кнопка. Сделайте так, чтобы по нажатию на кнопку в абзац загружалось с сервера содержимое страницы по адресу /ajax/.

Даны 5 кнопок и абзац. Даны также страницы /1/, /2/, /3/, /4/ и /5/.

Сделайте так, чтобы каждая из кнопок подгружала в абзац соответствующую страницу.

Дана одна кнопка и страницы /1/, /2/, /3/, /4/ и /5/.

Пусть первое нажатие на кнопку подгружает первую страницу, второе нажатие - вторую, и так далее, пока страницы не закончатся.

Дана кнопка, абзац и страница /ajax/, которая возвращает текущее время. Сделайте так, чтобы по нажатию на кнопку в абзац загружалось с сервера содержимое страницы по адресу /ajax/.

Дана кнопка, список ul и страница /ajax/, которая возвращает текущее время. Сделайте так, чтобы по нажатию на кнопку с сервера загружалось содержимое страницы /ajax/ и добавлялось в новый тег li тега ul.

Модифицируйте предыдущую задачу так, чтобы вместо кнопки работал таймер, который каждые 2 секунды будет опрашивать страницу /ajax/ и добавлять результат в новый тег li тега ul.