0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Простые приложения в браузере, например калькулятор, могут работать сами по себе без взаимодействия с внешним миром. Все что требуется для их реализации, это написать js-код, который рисует интерфейс и обновляет DOM реагируя на события ввода чисел и клика по кнопкам.</p>
1
<p>Простые приложения в браузере, например калькулятор, могут работать сами по себе без взаимодействия с внешним миром. Все что требуется для их реализации, это написать js-код, который рисует интерфейс и обновляет DOM реагируя на события ввода чисел и клика по кнопкам.</p>
2
<p>Но такие приложения редко встречаются в реальной жизни, так как с их помощью можно решить ограниченный набор задач. Гораздо чаще, код в браузере взаимодействует с внешним миром за пределами браузера. Такие приложения состоят из двух компонентов: клиентской части (client-side) и серверной (backend), где клиент и сервер общаются друг с другом посредством HTTP-запросов. HTTP-запросы с клиентской стороны делаются с помощью механизма, который долгое время назывался<strong>Ajax</strong>, сейчас так говорят реже, но мы для простоты оставим это название. Но иногда вы будете видеть названия<strong>XHR</strong>или<strong>Fetch</strong>.</p>
2
<p>Но такие приложения редко встречаются в реальной жизни, так как с их помощью можно решить ограниченный набор задач. Гораздо чаще, код в браузере взаимодействует с внешним миром за пределами браузера. Такие приложения состоят из двух компонентов: клиентской части (client-side) и серверной (backend), где клиент и сервер общаются друг с другом посредством HTTP-запросов. HTTP-запросы с клиентской стороны делаются с помощью механизма, который долгое время назывался<strong>Ajax</strong>, сейчас так говорят реже, но мы для простоты оставим это название. Но иногда вы будете видеть названия<strong>XHR</strong>или<strong>Fetch</strong>.</p>
3
<p>Возьмем для примера редактор Code Basics. Когда пользователь нажимает кнопку "проверить" в редакторе, то клиентский код выполняет запрос на серверную часть приложения, которая берет переданный код и запускает для него тесты. Результаты этих тестов возвращаются снова в браузер и Code Basics показывает результат выполнения этих тестов.</p>
3
<p>Возьмем для примера редактор Code Basics. Когда пользователь нажимает кнопку "проверить" в редакторе, то клиентский код выполняет запрос на серверную часть приложения, которая берет переданный код и запускает для него тесты. Результаты этих тестов возвращаются снова в браузер и Code Basics показывает результат выполнения этих тестов.</p>
4
<p>Все это происходит не моментально, поэтому во время проверки кнопка "проверить" блокируется и появляется спиннер. Дальше код на клиенте ждет пока придет ответ, причем предсказать время ответа невозможно. HTTP это сеть, а сеть это задержки, разрывы и плавающая скорость. Что-то может пойти не так на сервере, у клиента на машине или по пути между ними. Поэтому работа с сетью требует дополнительных усилий, особенно в области обработки ошибок.</p>
4
<p>Все это происходит не моментально, поэтому во время проверки кнопка "проверить" блокируется и появляется спиннер. Дальше код на клиенте ждет пока придет ответ, причем предсказать время ответа невозможно. HTTP это сеть, а сеть это задержки, разрывы и плавающая скорость. Что-то может пойти не так на сервере, у клиента на машине или по пути между ними. Поэтому работа с сетью требует дополнительных усилий, особенно в области обработки ошибок.</p>
5
<p>Обратите внимание на нижнюю часть скриншота. На нем выбрана вкладка Network в DevTools. На этой вкладке отображаются все запросы к серверу, включая Ajax-запросы. Для удобства их можно отфильтровать, чтобы не мешать с другими запросами выбрав<strong>XHR/Fetch</strong>. Эта логика работает похожим образом во всех браузерах.</p>
5
<p>Обратите внимание на нижнюю часть скриншота. На нем выбрана вкладка Network в DevTools. На этой вкладке отображаются все запросы к серверу, включая Ajax-запросы. Для удобства их можно отфильтровать, чтобы не мешать с другими запросами выбрав<strong>XHR/Fetch</strong>. Эта логика работает похожим образом во всех браузерах.</p>
6
<p><em>Попробуйте сейчас открыть в отдельной вкладке code-basics.com зайти в любой урок любого курса (регистрация не требуется) и запустить проверку, предварительно открыв вкладку Network. В конце списка вы увидите запрос на сервер. Попробуйте нажать на него и изучить</em>.</p>
6
<p><em>Попробуйте сейчас открыть в отдельной вкладке code-basics.com зайти в любой урок любого курса (регистрация не требуется) и запустить проверку, предварительно открыв вкладку Network. В конце списка вы увидите запрос на сервер. Попробуйте нажать на него и изучить</em>.</p>
7
<p>На запрос можно нажать, тогда вы сможете увидеть более подробную информацию о нем. Какой был выполнен запрос, куда, с какими заголовками и данными. Там же есть вся информация об ответе. Если запрос вернул ошибку, то браузеры для удобства выделяют их красным цветом.</p>
7
<p>На запрос можно нажать, тогда вы сможете увидеть более подробную информацию о нем. Какой был выполнен запрос, куда, с какими заголовками и данными. Там же есть вся информация об ответе. Если запрос вернул ошибку, то браузеры для удобства выделяют их красным цветом.</p>
8
<p>Технически HTTP-запросы из браузера делаются с помощью<strong>Fetch API</strong>представленного одной единственной функцией fetch(), которая доступна глобально. Она реализована во всех современных браузерах, поэтому ее использовать безопасно.</p>
8
<p>Технически HTTP-запросы из браузера делаются с помощью<strong>Fetch API</strong>представленного одной единственной функцией fetch(), которая доступна глобально. Она реализована во всех современных браузерах, поэтому ее использовать безопасно.</p>
9
<h2>Fetch</h2>
9
<h2>Fetch</h2>
10
<p>fetch() асинхронная функция, которая выполняет запрос HTTP-запрос по указанному адресу с нужными заголовками и данными. Посмотрите пример вызова прямо в браузере на сайте code-basics.com:</p>
10
<p>fetch() асинхронная функция, которая выполняет запрос HTTP-запрос по указанному адресу с нужными заголовками и данными. Посмотрите пример вызова прямо в браузере на сайте code-basics.com:</p>
11
<p>Попробуйте скопировать эти строки и выполнить запрос в консоли браузера.</p>
11
<p>Попробуйте скопировать эти строки и выполнить запрос в консоли браузера.</p>
12
<p>Несколько наблюдений:</p>
12
<p>Несколько наблюдений:</p>
13
<ul><li>По умолчанию используется метод<em>GET</em>.</li>
13
<ul><li>По умолчанию используется метод<em>GET</em>.</li>
14
<li>Если домен не указан, то запрос идет на тот же домен, где происходит вызов, в нашем примере это<a>https://code-basics.com</a>.</li>
14
<li>Если домен не указан, то запрос идет на тот же домен, где происходит вызов, в нашем примере это<a>https://code-basics.com</a>.</li>
15
<li>Данные ответа не лежат в готовом виде внутри response, их нужно так же извлекать с помощью асинхронного вызова. Это сделано на случай использования стриминга (streaming), когда данные с сервера отдаются не сразу, а по частям.</li>
15
<li>Данные ответа не лежат в готовом виде внутри response, их нужно так же извлекать с помощью асинхронного вызова. Это сделано на случай использования стриминга (streaming), когда данные с сервера отдаются не сразу, а по частям.</li>
16
</ul><p>Метод text() используется в том случае, если запрос возвращает данные не в структурированном виде, например в виде HTML. Для работы с JSON понадобится другой метод - json(). В таком случае данные сразу вернутся в виде готового объекта.</p>
16
</ul><p>Метод text() используется в том случае, если запрос возвращает данные не в структурированном виде, например в виде HTML. Для работы с JSON понадобится другой метод - json(). В таком случае данные сразу вернутся в виде готового объекта.</p>
17
<p>С помощью fetch() можно не только запрашивать данные, но и отправлять их на сервер. Типичный пример это отправка формы. Для этого вторым параметром в вызов fetch() передается объект, где указывается нужный метод, заголовки и данные. Для отправки данных в формате JSON, нужно добавить правильный заголовок<em>Content-Type</em>и выполнить преобразование данных с помощью JSON.stringify().</p>
17
<p>С помощью fetch() можно не только запрашивать данные, но и отправлять их на сервер. Типичный пример это отправка формы. Для этого вторым параметром в вызов fetch() передается объект, где указывается нужный метод, заголовки и данные. Для отправки данных в формате JSON, нужно добавить правильный заголовок<em>Content-Type</em>и выполнить преобразование данных с помощью JSON.stringify().</p>
18
<h2>Полный пример отправки формы</h2>
18
<h2>Полный пример отправки формы</h2>
19
<p>Соберем все вместе и посмотрим на то, как можно реализовать отправку формы используя Ajax. Допустим у нас есть форма регистрации с полями для ввода имени и email:</p>
19
<p>Соберем все вместе и посмотрим на то, как можно реализовать отправку формы используя Ajax. Допустим у нас есть форма регистрации с полями для ввода имени и email:</p>
20
<p>Тогда для реализации отправки нам понадобится выполнить следующие шаги:</p>
20
<p>Тогда для реализации отправки нам понадобится выполнить следующие шаги:</p>
21
<ol><li>Повесить асинхронный обработчик на событие "отправка формы".</li>
21
<ol><li>Повесить асинхронный обработчик на событие "отправка формы".</li>
22
<li>В обработчике извлечь данные формы с помощью formData.</li>
22
<li>В обработчике извлечь данные формы с помощью formData.</li>
23
<li>Выполнить отправку данных на<em>/users/new</em>с помощью fetch().</li>
23
<li>Выполнить отправку данных на<em>/users/new</em>с помощью fetch().</li>
24
<li>Сообщить пользователю о результатах отправки.</li>
24
<li>Сообщить пользователю о результатах отправки.</li>
25
</ol><p>fetch() - это довольно низкоуровневый механизм. Например, при работе с JSON нам приходится самостоятельно выставлять заголовки и сериализовывать данные с помощью JSON.stringify(). Из-за этого широкую популярность приобрела библиотека<a>axios</a>, которая работает в базовом варианте практически идентично, но автоматизирует рутину.</p>
25
</ol><p>fetch() - это довольно низкоуровневый механизм. Например, при работе с JSON нам приходится самостоятельно выставлять заголовки и сериализовывать данные с помощью JSON.stringify(). Из-за этого широкую популярность приобрела библиотека<a>axios</a>, которая работает в базовом варианте практически идентично, но автоматизирует рутину.</p>
26
<h2>Работа с параметрами запроса (query params)</h2>
26
<h2>Работа с параметрами запроса (query params)</h2>
27
<p>Если ваш запрос на сервер содержит параметры запроса, то их придется добавлять в адрес запроса самостоятельно, fetch() не умеет с ними работать.</p>
27
<p>Если ваш запрос на сервер содержит параметры запроса, то их придется добавлять в адрес запроса самостоятельно, fetch() не умеет с ними работать.</p>
28
<p>Но это не ошибка или недоработка дизайна функции. Так и было задумано, чтобы не перегружать fetch(), той функциональностью, которая уже добавлена в браузере: URL и URLSearchParams.</p>
28
<p>Но это не ошибка или недоработка дизайна функции. Так и было задумано, чтобы не перегружать fetch(), той функциональностью, которая уже добавлена в браузере: URL и URLSearchParams.</p>
29
<p>fetch() умеет работать с объектом URL напрямую, для этого достаточно передать его первым параметром вместо строки:</p>
29
<p>fetch() умеет работать с объектом URL напрямую, для этого достаточно передать его первым параметром вместо строки:</p>
30
<h2>HTTP access control (CORS)</h2>
30
<h2>HTTP access control (CORS)</h2>
31
<p>В отличие от бэкенда, HTTP-запросы на клиенте могут использоваться злоумышленниками для кражи данных. Поэтому браузеры контролируют, куда и как делаются запросы. Подробно об этом механизме можно прочитать<a>тут</a></p>
31
<p>В отличие от бэкенда, HTTP-запросы на клиенте могут использоваться злоумышленниками для кражи данных. Поэтому браузеры контролируют, куда и как делаются запросы. Подробно об этом механизме можно прочитать<a>тут</a></p>