← Назад к вопросам
Как получаются значения асинхронной операции?
1.0 Junior🔥 111 комментариев
#Soft Skills и рабочие процессы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Получение значений асинхронных операций
Что такое асинхронная операция
Асинхронная операция — это операция, которая не выполняется сразу и возвращает результат не сразу, а в будущем. Примеры:
- Запрос к API
- Чтение файла
- Таймер
- Событие клика
Способы получить значения
1. Callbacks (старый способ, устаревший)
// Плохо: callback hell
fetchUser(1, (user) => {
fetchPosts(user.id, (posts) => {
fetchComments(posts[0].id, (comments) => {
console.log(comments);
});
});
});
Проблемы:
- Читается справа налево (pyramid of doom)
- Сложно обрабатывать ошибки
- Сложно отменить операцию
2. Promises (современный стандарт)
// Хорошо: читается слева направо
fetchUser(1)
.then((user) => fetchPosts(user.id))
.then((posts) => fetchComments(posts[0].id))
.then((comments) => console.log(comments))
.catch((error) => console.error(error));
Структура Promise:
const promise = new Promise((resolve, reject) => {
// Асинхронная операция
setTimeout(() => {
if (success) {
resolve('Успешный результат'); // Выполнено
} else {
reject('Ошибка'); // Отклонено
}
}, 1000);
});
promise
.then((result) => console.log(result))
.catch((error) => console.error(error))
.finally(() => console.log('Готово'));
3. Async/Await (самый современный способ)
// Лучше всего: выглядит как синхронный код
async function getComments() {
try {
const user = await fetchUser(1);
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
console.log(comments);
return comments;
} catch (error) {
console.error(error);
}
}
await getComments();
Практические примеры в React
1. Fetch данных с API
function Posts() {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch('/api/posts');
if (!response.ok) throw new Error('Failed');
const data = await response.json();
setPosts(data);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
2. Promise.all для параллельных операций
// Плохо: последовательное выполнение (долго)
async function getDataSequential() {
const user = await fetchUser(1); // 1 сек
const posts = await fetchPosts(1); // 1 сек
const comments = await fetchComments(); // 1 сек
return { user, posts, comments }; // Всего: 3 сек
}
// Хорошо: параллельное выполнение (быстро)
async function getDataParallel() {
const [user, posts, comments] = await Promise.all([
fetchUser(1), // 1 сек
fetchPosts(1), // 1 сек (параллельно)
fetchComments(), // 1 сек (параллельно)
]); // Всего: 1 сек
return { user, posts, comments };
}
3. Promise.race для таймаутов
// Либо данные пришли, либо истёк timeout
const data = await Promise.race([
fetch('/api/data'),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), 5000)
),
]);
TanStack Query для асинхронных данных (рекомендуется)
import { useQuery } from '@tanstack/react-query';
function Posts() {
// Все сложности с кэшированием, retry, loading states
// решаются автоматически
const { data: posts, isLoading, error } = useQuery({
queryKey: ['posts'],
queryFn: async () => {
const res = await fetch('/api/posts');
return res.json();
},
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error</div>;
return <PostsList posts={posts} />;
}
Обработка ошибок
1. Try/Catch
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
// Ловим сетевые ошибки и ошибки парсинга JSON
console.error('Failed to fetch:', error);
throw error; // Пробросим дальше если нужно
}
}
2. Проверка статуса
async function fetchData() {
const response = await fetch('/api/data');
// fetch НЕ бросает ошибку на 404/500!
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
3. Custom Error Handling
class APIError extends Error {
constructor(
public status: number,
public data: any,
message?: string
) {
super(message || `API Error ${status}`);
}
}
async function fetchWithErrorHandling(url: string) {
const response = await fetch(url);
if (!response.ok) {
const data = await response.json();
throw new APIError(response.status, data);
}
return response.json();
}
try {
const data = await fetchWithErrorHandling('/api/data');
} catch (error) {
if (error instanceof APIError) {
console.log(`API returned ${error.status}: ${error.data.message}`);
}
}
Отмена асинхронных операций
function Posts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const response = await fetch('/api/posts', {
signal: controller.signal, // Передаём сигнал
});
const data = await response.json();
setPosts(data);
} catch (error) {
if (error instanceof DOMException && error.name === 'AbortError') {
console.log('Fetch was cancelled');
}
}
};
fetchData();
// Отмены fetch если компонент умрёт
return () => controller.abort();
}, []);
return <div>{posts.length} posts</div>;
}
Последовательность операций с async/await
// Операция 2 зависит от операции 1
async function createAndFetchPost() {
try {
// 1. Создаём пост
const createResponse = await fetch('/api/posts', {
method: 'POST',
body: JSON.stringify({ title: 'New Post' }),
});
const newPost = await createResponse.json();
// 2. Затем загружаем все посты
const allResponse = await fetch('/api/posts');
const allPosts = await allResponse.json();
return { newPost, allPosts };
} catch (error) {
console.error('Failed:', error);
}
}
Вывод
Современный фронтенд в 2026:
1. Используй async/await, а не .then().then()
2. Для асинхронных данных в React — используй TanStack Query
3. Всегда обрабатывай ошибки (try/catch или .catch())
4. Для параллельных операций — Promise.all()
5. Для таймаутов — Promise.race() или AbortController
6. Не забывай отменять запросы при unmount компонента
Асинхронность — основа современного веб-разработки, важно понимать, как работают Promises и async/await.