Что такое callback-функция в JavaScript?

546 прочитали

What the heck is a Callback?!
What the heck is a Callback?!

(фото любезно заимствованно с данного сайта)

Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?

Что такое коллбэк?

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

Чуть сложнее: В JavaScript функции — это объекты. Поэтому функции могут принимать другие функции в качестве аргументов, а также функции могут возвращать функции в качестве результата. Функции, которые это умеют, называются функциями высшего порядка. А любая функция, которая передается как аргумент, называется callback-функцией. Чтобы лучше разобраться, давайте посмотрим на примерах, как это выглядит.

Зачем нам нужны коллбэки?

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

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-2

Как вы и ожидаете, функция first выполнится первой, а функция second после нее, и в консоли будет выведен следующий результат:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-3

Пока что все понятно. Но что если функция first содержит некий код, который не может выполнится немедленно? К примеру, запрос к API, где мы отправляем запрос и должны ждать ответа. Чтобы смоделировать такую ситуацию, мы используем функцию setTimeout, которая вызывает функцию после заданного временного промежутка. Мы отсрочим выполнение функции на 500 миллисекунд, как будто бы это запрос к некому API. Теперь код будет выглядеть так:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-4

Неважно, понимаете ли вы сейчас, как работает setTimout(). Основная идея – теперь мы отложили исполнение команды console.log(1) на 500 миллисекунд. И что теперь выведет наша программа?

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-5

Хотя мы по-прежнему вызываем функцию first первой, ее вывод появился вторым, после вывода функции second. Но JavaScript не нарушает порядок вызова функций, он просто не дожидается ответа от функции first, а сразу двигается дальше – к функции second.

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

Создаем callback

Хватит болтовни, теперь давайте создадим коллбэк.

Во-первых, откройте консоль разработчика в Google Chrome (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J) и введите в консоли следующую функцию:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-6

Мы создали функцию doHomework. Наша функция принимает одну переменную – название предмета, которым мы будем заниматься. Вызовите функцию, набрав следующий текст в консоли:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-7

Теперь давайте добавим в определение функции еще один параметр, это и будет наш коллбэк. Затем вызовем ее, определив функцию-callback в качестве аргумента:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-8

Если вы введете этот код в консоли, вы получите два алерта один за другим, в первом будет сообщение о том, что выполнение домашнего задания началось (Starting my math homework.), а во втором — что вы закончили выполнять задание (Finished my homework).

Однако коллбэки не обязательно быть определены при вызове функции. Они могут быть определены и в другом месте кода, например, так:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-9

Таким образом, результат выполнения этого кода, такой же, как и в предыдущем примере, однако сам код немного другой. Как вы видите, мы передали функцию alertFinished как аргумент в функцию doHomework при ее вызове.

Пример из реальной жизни

На прошлой неделе я опубликовал статью «Создаем бота для Твиттера в 38 строк кода». Этот код работает благодаря API Твиттера. И когда мы делаем запрос к API, мы должны дождаться ответа до того, как начнем выполнять с этим ответом какие-то действия. Это прекрасный пример того, как в реальной жизни выглядит callback-функция. Вот как выглядит сам запрос:

  (фото любезно заимствованно с данного сайта) Это перевод статьи Брэндона Морелли “JavaScript: What the heck is a Callback?” Что такое коллбэк?-10

T.get просто значит, что мы выполняем get запрос к API Твиттера. В запросе три параметра: 'search/tweets' – это адрес (роут) запроса, params – наши параметры поиска и в конце передается анонимная функция-callback.

Коллбэк здесь нужен, потому что нам нужно дождаться ответа от сервера до того, как приступим к дальнейшему выполнению кода. Мы не знаем, успешным будет наш запрос или нет, поэтому после отправки параметров поиска на search/tweets через get-запрос, мы просто ждем. Как только Твиттер ответит, выполнится наша callback-функция. Твиттер отправит нам в качестве ответа или объект err (error – ошибка), или объект response. В коллбэке мы можем через if() проверить, был ли запрос успешным или нет, и затем действовать соответственно.

Перевод: Артем Арбатский

________

От редактора: Мы на Хекслете часто публикуем переводы статей. Важно помнить:

  • Мнение автора статьи может отличаться от мнения администрации и сотрудников Хекслета.
  • Цель перевода — показать мнение. Поэтому одна статья может визуально противоречить другой: это просто разные мнения. Мы оставляем на вашу ответственность возможность анализировать и делать выводы для себя.

Originally published at ru.hexlet.io.