Без обратных вызовов было бы очень сложно сделать что-то интересное с помощью JavaScript. Обратные вызовы были в языке с самого начала, но применение обратных вызовов росло все больше и больше. На самом деле многие новые шаблоны, добавленные в язык за последние годы, делают возможным использование обратных вызовов более интересными способами.

Но я забегаю вперед. Давайте сначала определим обратные вызовы на нескольких примерах, а затем рассмотрим два основных способа использования обратных вызовов в JavaScript.

Определение обратных вызовов с примерами

Проще говоря, обратный вызов — это функция, которая передается в другую функцию в качестве аргумента, а затем в какой-то момент в будущем эта функция вызывается для выполнения дополнительной задачи. Название «обратный вызов» происходит от того факта, что код вызывает функцию, которая была передана.

Природа функций в JavaScript позволяет выполнять обратные вызовы. Тот факт, что они относятся к первому классу и могут быть более высокого порядка, делает это возможным. Я погружаюсь в обе концепции в другой статье.

Из-за природы функций у нас есть ряд встроенных методов, которые используют обратные вызовы. Это хороший способ представить их. Например, давайте взглянем на метод карты, доступный для массивов.

Метод карты перебирает каждый элемент массива и применяет функцию обратного вызова к каждому элементу. Конечным результатом является новый массив. В только что приведенном примере мы передаем функцию обратного вызова, которая просто удваивает число в массиве. В этом примере функция обратного вызова вызывается 6 раз; один раз для каждого элемента в исходном массиве.

Обычный шаблон обратного вызова, который мы видим при работе с HTML-страницами, — это создание прослушивателей событий. addEventListener method является предпочтительным шаблоном для добавления слушателей к объекту DOM. Требуется функция обратного вызова.

После создания этого прослушивателя он будет реагировать на любое нажатие клавиши, вызывая функцию обратного вызова. Затем строковый эквивалент нажатой клавиши отображается в консоли.

Мы также можем создавать собственные функции, использующие обратные вызовы. Во многих случаях это может сделать функцию более гибкой.

В этом примере у нас есть функция updateObjs, которая принимает любой объект, а затем обновляет значения этого объекта с помощью переданной функции. Сначала мы вызываем ее, чтобы обновить все числа до фактических чисел, а не строк. Затем мы вызываем его, чтобы обновить все строки, сделав первую букву заглавной.

Функция updateObjs становится более гибкой, и нам нужно написать код, который выполняет итерацию по объекту только один раз. Это показывает некоторые преимущества написания кода, использующего обратные вызовы.

Синхронные обратные вызовы

Функции обратного вызова можно использовать в синхронных или асинхронных шаблонах.

Предыдущий пример представляет собой синхронный шаблон. Код выполняется последовательно от начала до конца и блокирует запуск дополнительного кода до его завершения. Эта последовательная природа включает вызов обратного вызова. Обратный вызов становится частью последовательно выполняемого кода и должен завершиться до запуска дополнительного кода.

Но обратные вызовы также важны для асинхронного кода в JavaScript и составляют некоторые интересные вещи, которые мы можем делать с помощью JavaScript.

Асинхронные обратные вызовы

Вероятно, наиболее часто упоминаемым асинхронным фрагментом кода, использующим обратный вызов, является setTimeout.

Функция setTimeout позволяет нам вызывать другую функцию через определенное время. Таймер обрабатывается внешней средой, браузером, поэтому он не блокирует выполнение дополнительного кода. По истечении времени обратный вызов помещается в очередь сообщений, а затем добавляется в стек вызовов для выполнения при наличии свободного места.

Основываясь на выводе консоли, второй оператор console.log выполняется перед функцией обратного вызова, даже если время установлено на 0 миллисекунд. Таким образом, в этом асинхронном примере не происходит блокировки кода. Однако без обратного вызова мы не смогли бы этого добиться.

Другой асинхронный шаблон, использующий обратные вызовы, — это промис. Промисы обычно используются, когда мы ожидаем завершения какой-либо асинхронной операции.

Например, Fetch API позволяет нам получать данные с сайтов. Однако нам не нужно ждать, пока код завершится. Другой код может выполняться, пока мы ждем, пока сайт вернет данные.

Fetch возвращает обещание после завершения, мы должны обрабатывать возвращенные данные с помощью метода .then. Но для того, чтобы метод .then работал, нам нужно передать функцию обратного вызова. Обратный звонок необходим. Таким образом, первый обратный вызов, который мы используем в приведенном выше примере, преобразует ответ в объект JSON. Затем это возвращает другое обещание. Второй обратный вызов записывает элемент «todo» в консоль.

Как мы видим, код является асинхронным, поскольку оператор console.log отображается в консоли первым.

Заключение

Обратные вызовы занимают центральное место во многих вещах, которые мы делаем в JavaScript. Без них мы не смогли бы выполнить никакого асинхронного кодирования. Они также позволяют нам делать некоторые интересные вещи с нашим синхронным кодом. По сути, обратные вызовы необходимы для JavaScript.

Следите за многими другими статьями о JavaScript.

Прокомментируйте ниже, чтобы добавить свои мысли о существенной природе обратных вызовов.