Без обратных вызовов было бы очень сложно сделать что-то интересное с помощью 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.
Прокомментируйте ниже, чтобы добавить свои мысли о существенной природе обратных вызовов.