это набор правил и протоколов, которые позволяют различным программам общаться друг с другом
{
"id": 1,
"title": "Заголовок поста",
"body": "Текст поста",
"userId": 1
}
Обмен данным происходит при помощи JSON формата
текстовый формат представления и обмена структурированными данными
{
"student": {
"name": "Иван Петров",
"age": 15,
"grade": 9,
"isStudent": true,
"skills": ["HTML", "CSS", "JavaScript"],
"contacts": {
"email": "ivan@example.com",
"phone": "+7-900-123-45-67"
}
}
}
Основан на принципе представления данных в виде пар
«ключ — значение»
программа, которая отправляет HTTP запросы к серверу и получает ответы
современный способ выполнения HTTP запросов в JavaScript
Он возвращает Promise и работает асинхронновозможность выполнения операций, не блокируя основной поток выполнения программы
const timer = setTimeout(() => console.log("Я второй"), 60000)
console.log("Я первый")
объект в JavaScript, который представляет результат асинхронной операции (который будет известен в будущем)
.then(result => { ... })
— выполняется, если операция завершилась
успешно.
.catch(error => { ... })
— выполняется, если произошла ошибка.
.finally(() => { ... })
— выполняется в любом случае (успех или
ошибка).
const fetchData = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve("Данные успешно получены!");
} else {
reject("Ошибка при получении данных");
}
}, 2000);
});
fetchData
.then(result => {
console.log(result); // "Данные успешно получены!"
})
.catch(error => {
console.error(error); // "Ошибка при получении данных"
})
.finally(() => {
console.log("Операция завершена");
});
Внутри можно использовать
await
, который останавливает выполнение внутри async
функции, пока Promise не вернётся с результатом
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve("Данные получены!"), 2000);
});
}
async function main() {
console.log("Первый");
const result = await fetchData();
console.log(result, "Второй, несмотря на задержку");
console.log("Третий");
}
main();
function getDataWithThen() {
return fetch("https://jsonplaceholder.typicode.com/todos/1")
.then(response => response.json())
.then(data => {
console.log("Данные получены:", data);
})
}
getDataWithThen();
async function getDataWithAwait() {
const response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
const data = await response.json();
console.log("Данные получены:", data);
}
getDataWithAwait();
Response
. У этого объекта есть специальные методы для чтения
тела ответа.
.json()читает тело ответа и преобразует его в JavaScript-объект/массив
.text()
который читает тело ответа (обычно
HTML
или
XML
) и возвращает его как строку
.blob()возвращает данные в виде Blob (Binary Large Object - набор единичек и ноликов ). Обычно используется для работы с файлами, изображениями, видео и аудио
Виды ошибок:
fetch("https://jsonplaceholder.typicode.com/invalid-url")
.then(response => {
if (!response.ok) {
throw new Error(`Ошибка HTTP: ${response.status}`);
}
return response.json();
})
.then(data => console.log("Данные:", data))
.catch(error => console.error("Ошибка запроса:", error))
.finally(() => console.log("Запрос завершён"));
async function fetchData() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/invalid-url");
if (!response.ok) {
throw new Error(`Ошибка HTTP: ${response.status}`);
}
const data = await response.json();
console.log("Данные:", data);
} catch (error) {
console.error("Ошибка запроса:", error);
} finally {
console.log("Запрос завершён");
}
}
fetchData();
try {
// Код, который может вызвать ошибку
} catch (error) {
// Код, который выполняется, если произошла ошибка
} finally {
// Код, который выполнится в любом случае (ошибка была или нет)
}
async function getUsers() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
const list = document.getElementById("user-list");
list.innerHTML = ""; // очищаем список перед вставкой
users.forEach(user => {
const li = document.createElement("li");
li.textContent = `${user.name} (${user.email})`;
list.appendChild(li);
});
} catch (error) {
console.error("Ошибка при загрузке:", error);
}
}
getUsers();
Пока данные загружаются с сервера, пользователь не должен видеть пустую страницу — нужно показывать состояние загрузки
Запрос выполняется, данные ещё не пришли
Данные успешно получены и отображены
Произошла ошибка при загрузке
Загрузка...
async function getUsers() {
const loader = document.getElementById("loader");
const list = document.getElementById("user-list");
loader.style.display = "block"; // показываем загрузку
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
users.forEach(user => {
const li = document.createElement("li");
li.textContent = user.name;
list.appendChild(li);
});
} catch (error) {
list.innerHTML = "Ошибка загрузки данных 😢 ";
} finally {
loader.style.display = "none"; // скрываем в любом случае
}
}
Вместо спиннера можно показать «скелет» будущего контента — заглушки нужного размера
.skeleton {
background: linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 50%, #e0e0e0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
height: 20px;
margin-bottom: 8px;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
function showSkeleton(list, count = 3) {
list.innerHTML = Array(count)
.fill('')
.join("");
}
механизм безопасности браузера, который ограничивает запросы к другому домену, протоколу или порту
https://mysite.com:443 ← origin вашего сайта
https://api.other.com ← другой домен → CORS!
http://mysite.com ← другой протокол → CORS!
https://mysite.com:8080 ← другой порт → CORS!
Браузер защищает пользователя: скрипт с одного сайта не должен тайно читать данные с другого сайта (например, из банка)
Access to fetch at 'https://api.example.com'
from origin 'https://mysite.com'
has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header
is present on the requested resource.
с заголовком
Origin: https://mysite.com
с заголовком
Access-Control-Allow-Origin
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin:
https://mysite.com
Заголовок отсутствует или содержит другой origin — браузер блокирует ответ
Перед «опасными» запросами браузер автоматически
отправляет предварительный запрос
OPTIONS
, чтобы спросить у сервера разрешение
OPTIONS /api/data HTTP/1.1
Origin: https://mysite.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
POST
/
PUT
/
DELETE
или при нестандартных заголовках (например,
Authorization
)
Попросить бэкенд добавить нужный заголовок
Access-Control-Allow-Origin:
https://mysite.com
Использовать прокси в dev-сервере (Vite, webpack)
// vite.config.js
server: {
proxy: {
'/api': 'http://localhost:3000'
}
}