Урок 22 из 25
В прогрессе

21) callBack()

Callback в JavaScript — это функция, переданная в другую функцию в качестве аргумента, которая затем вызывается по завершении определённой операции.

				
					function fetchData(callback) {
    setTimeout(() => {
        const data = { id: 1, name: "John" };
        callback(data); // Вызов callback с результатом
    }, 1000); // Симуляция задержки
}

function processData(data) {
    console.log("Полученные данные:", data);
}

fetchData(processData); // Передаём processData как callback

				
			
 
 
 

Алгоритм:

  1. Передаём функцию processData как аргумент.
  2. fetchData вызывает её после получения данных.

Преимущества:

  • Удобно для асинхронных операций.

Недостатки:

  • «Callback Hell» — вложенность при сложных цепочках.

Для избежания сложности используют Promises или async/await.

Callback Hell

Callback Hell — это ситуация, когда в коде появляется много вложенных callback-функций, что делает его трудно читаемым и сложным для поддержки.

Пример Callback Hell:

				
					function fetchData(callback) {
    setTimeout(() => {
        console.log("Данные загружены");
        callback();
    }, 1000);
}

function processData(callback) {
    setTimeout(() => {
        console.log("Данные обработаны");
        callback();
    }, 1000);
}

function saveData(callback) {
    setTimeout(() => {
        console.log("Данные сохранены");
        callback();
    }, 1000);
}

// Вызов функций с вложенными callback'ами
fetchData(() => {
    processData(() => {
        saveData(() => {
            console.log("Вся операция завершена");
        });
    });
});

				
			

Почему это плохо?

  1. Плохая читаемость: код становится сложным из-за большой вложенности.
  2. Сложность отладки: ошибки трудно отследить.
  3. Трудность в изменении: добавление новых функций ухудшает структуру.

Решение Callback Hell:

Использование Promises:

				
					function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("Данные загружены");
            resolve();
        }, 1000);
    });
}

function processData() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("Данные обработаны");
            resolve();
        }, 1000);
    });
}

function saveData() {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log("Данные сохранены");
            resolve();
        }, 1000);
    });
}

fetchData()
    .then(processData)
    .then(saveData)
    .then(() => {
        console.log("Вся операция завершена");
    });

				
			

Использование async/await:

				
					async function main() {
    await fetchData();
    await processData();
    await saveData();
    console.log("Вся операция завершена");
}

main();

				
			

Promises

Promises (промисы) в JavaScript — это объект для работы с асинхронными операциями. Они позволяют писать более удобный и читаемый код по сравнению с колбэками.


Основные состояния Promise:

  1. Pending (в ожидании) — операция ещё не завершена.
  2. Fulfilled (выполнено) — операция успешно завершена.
  3. Rejected (отклонено) — операция завершилась с ошибкой.
				
					//Создание Promise:
const promise = new Promise((resolve, reject) => {
    const success = true; // Условие выполнения

    if (success) {
        resolve("Операция выполнена успешно!"); // Успешное завершение
    } else {
        reject("Ошибка выполнения!"); // Завершение с ошибкой
    }
});

// Обработка результата
promise
    .then(result => {
        console.log(result); // Если resolve
    })
    .catch(error => {
        console.error(error); // Если reject
    });

				
			

Пример: асинхронная операция

				
					function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const data = { id: 1, name: "John" };

            if (data) {
                resolve(data); // Успех
            } else {
                reject("Ошибка загрузки данных"); // Ошибка
            }
        }, 1000); // Симуляция задержки
    });
}

fetchData()
    .then(data => console.log("Данные:", data)) // Успешно
    .catch(error => console.error("Ошибка:", error)); // Ошибка

				
			

Преимущества Promises:

  1. Читаемость кода.
  2. Устранение «Callback Hell».
  3. Удобная обработка ошибок.

Комбинация с async/await:

				
					async function fetchData() {
    try {
        const data = await new Promise(resolve => setTimeout(() => resolve({ id: 1, name: "John" }), 1000));
        console.log(data);
    } catch (error) {
        console.error("Ошибка:", error);
    }
}

fetchData();
				
			

async/await

async/await — это современный синтаксис для работы с асинхронными операциями в JavaScript. Они предоставляют более читаемый способ работы с промисами, делая код линейным и простым.


Ключевые моменты:

  1. async: делает функцию асинхронной, заставляя её возвращать промис.
  2. await: используется внутри async-функций для ожидания выполнения промиса.
				
					async function fetchData() {
    return "Данные успешно загружены";
}

fetchData().then(data => console.log(data)); // Вывод: "Данные успешно загружены"

				
			

Использование await для работы с промисами:

				
					function getData() {
    return new Promise(resolve => {
        setTimeout(() => resolve("Данные получены!"), 1000);
    });
}

async function process() {
    console.log("Ожидание данных...");
    const data = await getData(); // Ждём завершения промиса
    console.log(data); // Вывод: "Данные получены!"
}

process();

				
			
  • await «останавливает» выполнение функции, пока промис не завершится.
  • Код выглядит синхронным, хотя выполняется асинхронно.

Обработка ошибок с try/catch:

				
					function fetchData(shouldFail) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (shouldFail) {
                reject("Ошибка загрузки данных");
            } else {
                resolve("Данные успешно загружены");
            }
        }, 1000);
    });
}

async function process() {
    try {
        const data = await fetchData(false); // Попробуйте true для ошибки
        console.log(data);
    } catch (error) {
        console.error("Ошибка:", error); // Обработка ошибки
    }
}

process();

				
			

Последовательное выполнение:

				
					function step1() {
    return new Promise(resolve => setTimeout(() => resolve("Шаг 1 выполнен"), 1000));
}

function step2() {
    return new Promise(resolve => setTimeout(() => resolve("Шаг 2 выполнен"), 1000));
}

async function runSteps() {
    const result1 = await step1();
    console.log(result1);

    const result2 = await step2();
    console.log(result2);
}

runSteps();
// Вывод:
// Шаг 1 выполнен
// Шаг 2 выполнен

				
			

Преимущества async/await:

  1. Читаемость кода.
  2. Удобная обработка ошибок через try/catch.
  3. Легко заменяет цепочки .then и .catch.

Ограничения:

  • Работает только внутри async-функций.
  • Ожидание с await замедляет выполнение, если нужно запускать задачи параллельно (лучше использовать Promise.all).

async/await упрощает работу с асинхронностью, делая код понятным и линейным.