Новички в программировании привыкают писать синхронный код во время обучения, когда одно действие происходит за другим, так выстраиваются целые страницы кода. Простые программы и приложения построены на синхронном программировании. Проблемы начинаются, когда преподаватель переходит к объяснению callback-функций.
Это уже асинхронное программирование. Такой процесс важен в обучении написания кода на JavaScript. Без асинхронного программирования не обходится ни одно сложное приложение.
Давайте посмотрим, что собой представляют Callback-функции и как пишут асинхронный код опытные программисты на JavaScript.
Что такое callback-функции
Callback-функция — это функция обратного вызова. Словосочетание образовано из двух английских: call — «вызов» и back — «назад, обратно». В программировании она нужна для передачи исполняемого кода в качестве аргумента другому коду, который вызывает её по завершении какого-либо действия.
Внимание! Callback-функция — это функция, исполняемая после того, как другая функция закончит исполнение.
Рассмотрим два примера. Один из реальной жизни, чтобы было понятно, о чём идёт речь. После него попробуем обратиться к конкретным примерам из программирования JavaScript.
-
Пример №1. Принцип работы callback-функции похож на заказ обратного звонка. Например, вы звоните в МТС Exolve, чтобы заказать интеграцию amoCRM и Telegram. Автоответчик сообщает, что операторы все заняты. Когда один из них освободится, он перезвонит вам. Вы кладёте трубку и идёте заниматься своими делами. Спустя некоторое время оператор перезванивает, и вы заказываете настройку интеграции amoCRM и Telegram. Вы же не начинаете интеграцию самостоятельно. Иначе вы совершили бы много ошибок.
-
Пример №2. То же самое происходит и в программировании. Разработчик задаёт запрос, прописывает callback-функцию, пишет код дальше. Запрос уходит к API, допустим, Telegram. Мы не выполняем никаких действий, а ждём, пока придёт ответ. Когда Telegram ответит, callback-функция выполнится. Будет отправлен объект Error или Response. В коде с callback мы сможем проверить с помощью if(), успешным был запрос или нет. Далее уже можно работать над кодом соответственно полученному ответу.
Если будет выполнен ответ на запрос раньше, чем придёт настоящий ответ, то возникнет коллизия. Она может убить дальнейший ход выполнения кода в приложении, из-за чего программа перестанет работать.
Это интересно! При написании асинхронного кода разработчики сталкиваются с «Пирамидой Судьбы» (Pyramid of Doom). Эта ошибка связана с неудобочитаемостью кода. Она возникает, когда программисты используют множество уровней с вложенными отступами для управления доступом к функции. Действительно, код начинает напоминать пирамиду, лежащую на боку.
С «Пирамидой Судьбы» сталкиваются программисты, которые читают чужой код, проверяя нулевые указатели. Pyramid of Doom не обходит стороной разработчиков приложений, обрабатывающих функции обратного вызова. Чтобы другим, да и самому себе, было приятно читать код, используйте форматирование.
Есть ещё и синхронные callback-функции. Их вы могли видеть при работе с вводом регистрационных данных. Например, написан код, который начинает работать, когда пользователь нажимает кнопку. Перед ним появляется пустое поле, которое он должен заполнить. Он прописывает имя и нажимает Enter. После нажатия этой клавиши отрабатывается код с синхронной callback-функцией.
Для чего нужны callback-функции
Во-первых, callback-функции сокращают написание кода. Не будь их, программисту пришлось бы прописывать все варианты вывода ответа в одной функции и выбирать их с помощью switch или if/else.
Во-вторых, JavaScript — это ориентированный на события язык программирования. Приложение, написанное на JS, продолжит выполнять другие действия вместо ожидания ответов на ушедшие запросы. Поэтому ввели функцию callback, чтобы остановить получение ответа до тех пор, пока не придёт реальный ответ от API.
В-третьих, эта функция делает код более удобочитаемым. Она даёт гибкость, удобство применения и изменения кода в последовательности действий.
Например, написание кода для серверов в среде Node.js полностью основано на асинхронном программировании и применении callback-функций.
Примеры callback-функций
Прежде рассмотрим, как работают функции без использования callback.
Напишем стандартный синхронный код:
function first(){
console.log(0);
}
function second(){
console.log(10);
}
first(0);
second(10);
Мы получим следующее:
// 0
// 10
Теперь давайте посмотрим на функцию first. Что будет, если она не сможет выполнить код сразу после запроса? Такое бывает при обращении к API сайтов. Ей нужно отправить запрос, а потом дождаться ответа. Чтобы создать случай подобного рода, запустим код setTimeout. Он отвечает за отсрочку действия прописанного кода.
const first = () => {
// Якобы создаётся запрос к API
setTimeout(() => {
console.log(0);
}, 350 );
};
const second = () => {
console.log(10);
};
first(0);
second(10);
В ответе мы увидим следующие строки:
// 10;
// 0.
Первым пришёл ответ от второй функции, потому что JavaScript продолжает работу, несмотря на задержку первой функции. Он просто не ждёт от неё ответа и выполняет свою работу.
Чтобы не случалось коллизий, вели callback-функцию.
const first = (callback) => {
// Имитируем запрос к API
setTimeout(() => {
console.log(0);
callback();
}, 350 );
};
const second = () => {
console.log(10);
};
first(second);
// 0
// 10
Таким образом работает эта функция. Она не даёт другим действиям происходить раньше получения запрошенного ответа.
Применение callback-функций
Возвращаемые функции используют:
-
для обращения к серверу
-
для анимации
-
для работы с файловой системой
-
для геолокации
Callback-функции часто применяют для написания кода для карт в приложениях 2GIS. Антивирусы используют их для проверки файлов. Хакеры могут встраивать обратные функции в вирусы. В этом случае они нужны для считывания паролей, набираемых пользователем.
Callback-функции используют сетевые фильтры. Так они собирают статистику и блокируют опасные пакеты с данными. Возвращаемые функции применяют и разработчики МТС Exolve.
Пишем callback-функцию в разделе с инструментами веб-разработчика Chrome
В блоке «Callback-функции» мы сказали об ошибке с названием Pyramid Of Doom. Поэтому, прежде чем начнёте писать callback-функцию, посмотрим, как избежать ошибок с таким громким названием.
Вот несколько советов:
-
используйте защитные операторы (Guard Clauses или Early Returns)
-
сравнивайте опции с точными значениями
-
извлекайте проверки переменных с контекстным именем
-
форматируйте и организовывайте код
Применяя эти знания, можно написать функцию обратного вызова в консоли браузера Chrome. Отследить стек вызовов асинхронных функций JS поможет инструмент Chrome Canary DevTools.
Чтобы запустить этот код в консоли Chrome, выполните следующие шаги:
-
Войдите на веб-страницу, на которой хотите выполнить этот код. У нас это будут «Новости» из ВК.
-
Откройте инструменты разработчика, кликнув по кнопке F12 либо правой кнопкой мыши на странице. Из выпавшего списка выберите «Инспектировать».
-
Перейдите во вкладку Console в инструментах разработчика.
-
Пропишите код с обратной функцией в консоль и нажмите Enter.
Вот пример выполнения callback-функции в JS:
// Функция, принимающая колбэк
function doSomethingAsync(callback) {
// Имитируем асинхронную задачу (например, задержка в две секунды)
setTimeout(function() {
console.log(«Асинхронная задача выполнена!»);
callback(); // Вызываем колбэк после выполнения задачи
}, 2000);
}
// Колбэк-функция, которая будет вызвана после завершения асинхронной задачи
function callbackFunction() {
console.log(«Колбэк-функция вызвана!»);
}
// Вызываем функцию с передачей колбэка
doSomethingAsync(callbackFunction);
Смотрим, что у вас получилось в итоге:
VM208:5 Асинхронная задача выполнена!
VM208:12 Колбэк-функция вызвана!
Если вы получили два ответа: «Асинхронная задача выполнена!» и «Колбэк-функция вызвана!», значит, вы всё сделали правильно.
Сегодня стараются уходить от использования функции callback, потому что есть такой термин, как Callback hell. Он означает, что в коде находится множество callback. Они другу друга вызывают, перевызывают так, что становится трудно читать код и искать ошибки. Программисты всё чаще используют такие асинхронные функции и операторы, как async и await. Они упрощают работу с кодом.
Заключение
Теперь вы знаете, для чего нужна callback-функция в языке программирования JavaScript. Используйте её всегда там, где долго нужно ждать ответов от API. Тогда вам не придётся самому прописывать ветвления (if/else), вы оптимизируете свою работу и увеличите эффективность кода.