JavaScript & TypeScriptМодуль 2: Функции
Callbacks
Функции как аргументы других функций
Цель урока
В этом уроке ты научишься:
- Передавать функции как аргументы
- Понимать callback-функции
- Видеть проблему callback hell
Что такое callback
Callback — это функция, которая передаётся в другую функцию как аргумент и вызывается позже.
function greet(name, callback) {
console.log("Привет, " + name + "!");
callback();
}
function sayBye() {
console.log("Пока!");
}
greet("Иван", sayBye);
// "Привет, Иван!"
// "Пока!"Зачем нужны callbacks
1. Обработка событий
document.addEventListener("click", function() {
console.log("Клик!");
});2. Асинхронные операции
setTimeout(function() {
console.log("Прошла 1 секунда");
}, 1000);3. Методы массивов
let numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(num) {
console.log(num * 2);
});
// 2, 4, 6, 8, 10Примеры callbacks
forEach
let fruits = ["яблоко", "банан", "апельсин"];
fruits.forEach(function(fruit, index) {
console.log(index + ": " + fruit);
});
// 0: яблоко
// 1: банан
// 2: апельсинmap
let numbers = [1, 2, 3];
let doubled = numbers.map(function(n) {
return n * 2;
});
console.log(doubled); // [2, 4, 6]filter
let numbers = [1, 2, 3, 4, 5, 6];
let even = numbers.filter(function(n) {
return n % 2 === 0;
});
console.log(even); // [2, 4, 6]Стрелочные функции как callbacks
let numbers = [1, 2, 3, 4, 5];
// Обычная функция
let doubled = numbers.map(function(n) {
return n * 2;
});
// Стрелочная функция
let doubled = numbers.map(n => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]Асинхронные callbacks
console.log("Начало");
setTimeout(function() {
console.log("Таймер сработал");
}, 1000);
console.log("Конец");
// Вывод:
// "Начало"
// "Конец"
// "Таймер сработал" (через 1 секунду)Асинхронность
Callback вызывается позже, после завершения операции. Код продолжает выполняться.
Callback Hell
Вложенные callbacks становятся нечитаемыми:
// Плохо — "пирамида смерти"
getUser(userId, function(user) {
getOrders(user.id, function(orders) {
getOrderDetails(orders[0].id, function(details) {
getProduct(details.productId, function(product) {
console.log(product);
});
});
});
});Проблема
Такой код сложно читать, отлаживать и поддерживать.
Решение — Promises и async/await
// Хорошо — с async/await
async function getProductInfo(userId) {
const user = await getUser(userId);
const orders = await getOrders(user.id);
const details = await getOrderDetails(orders[0].id);
const product = await getProduct(details.productId);
return product;
}Создание функций с callbacks
function fetchData(url, onSuccess, onError) {
// Имитация запроса
setTimeout(function() {
if (url.startsWith("http")) {
onSuccess({ data: "Данные загружены" });
} else {
onError("Неверный URL");
}
}, 1000);
}
fetchData(
"https://api.example.com",
function(result) {
console.log("Успех:", result);
},
function(error) {
console.log("Ошибка:", error);
}
);Практика
Задание 1: forEach
Задача: Выведи квадраты чисел массива.
Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
1 4 9 16 25
Задание 2: map
Задача: Преобразуй массив имён в приветствия.
Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
["Привет, Иван!","Привет, Мария!","Привет, Пётр!"]
Задание 3: Свой callback
Задача: Создай функцию repeat(n, callback), которая вызывает callback n раз.
Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Итерация 0 Итерация 1 Итерация 2
Проверь себя
- Что такое callback?
- Почему возникает callback hell?
- Чем стрелочные функции удобны для callbacks?