0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p><strong>Рассказываем, что такое коллбэк-функция в JavaScript, зачем ее использовать и как вообще она устроена.</strong></p>
1
<p><strong>Рассказываем, что такое коллбэк-функция в JavaScript, зачем ее использовать и как вообще она устроена.</strong></p>
2
<p><em>Это перевод статьи Брэндона Морелли<a>JavaScript: What the heck is a Callback?</a></em></p>
2
<p><em>Это перевод статьи Брэндона Морелли<a>JavaScript: What the heck is a Callback?</a></em></p>
3
<blockquote><p>Вы читаете обновленную и улучшенную версию нашей старой статьи</p>
3
<blockquote><p>Вы читаете обновленную и улучшенную версию нашей старой статьи</p>
4
</blockquote><h2>Содержание</h2>
4
</blockquote><h2>Содержание</h2>
5
<ul><li><a>Что такое коллбэк?</a></li>
5
<ul><li><a>Что такое коллбэк?</a></li>
6
<li><a>Зачем нужны коллбэки?</a></li>
6
<li><a>Зачем нужны коллбэки?</a></li>
7
<li><a>Создаем коллбэк</a></li>
7
<li><a>Создаем коллбэк</a></li>
8
<li><a>Пример из реальной жизни</a></li>
8
<li><a>Пример из реальной жизни</a></li>
9
</ul><h2>Что такое коллбэк?</h2>
9
</ul><h2>Что такое коллбэк?</h2>
10
<p><strong>Простыми словами:</strong>коллбэк - это функция, которая должна быть выполнена после того, как другая функция завершила выполнение (отсюда и название: callback - функция обратного вызова).</p>
10
<p><strong>Простыми словами:</strong>коллбэк - это функция, которая должна быть выполнена после того, как другая функция завершила выполнение (отсюда и название: callback - функция обратного вызова).</p>
11
<p><strong>Чуть сложнее:</strong>В JavaScript функции - это объекты. Поэтому функции могут принимать другие функции в качестве аргументов, а также возвращать функции в качестве результата. Функции, которые это умеют, называются функциями высшего порядка. А любая функция, которая передается как аргумент, называется callback-функцией.</p>
11
<p><strong>Чуть сложнее:</strong>В JavaScript функции - это объекты. Поэтому функции могут принимать другие функции в качестве аргументов, а также возвращать функции в качестве результата. Функции, которые это умеют, называются функциями высшего порядка. А любая функция, которая передается как аргумент, называется callback-функцией.</p>
12
<h2>Зачем нужны коллбэки?</h2>
12
<h2>Зачем нужны коллбэки?</h2>
13
<p>По одной простой причине: JavaScript - это<a>событийно-ориентированный язык</a>. Поэтому вместо того, чтобы ждать ответа для дальнейшего выполнения программы, JavaScript продолжит выполнение, одновременно ожидая других событий. Давайте разберем простой пример:</p>
13
<p>По одной простой причине: JavaScript - это<a>событийно-ориентированный язык</a>. Поэтому вместо того, чтобы ждать ответа для дальнейшего выполнения программы, JavaScript продолжит выполнение, одновременно ожидая других событий. Давайте разберем простой пример:</p>
14
<p>Как вы и ожидаете, функция first выполнится первой, а функция second уже после нее. Поэтому в консоли будет выведен следующий результат:</p>
14
<p>Как вы и ожидаете, функция first выполнится первой, а функция second уже после нее. Поэтому в консоли будет выведен следующий результат:</p>
15
<p>// 1 // 2</p>
15
<p>// 1 // 2</p>
16
<p>Пока что все понятно. Но что, если функция first содержит некий код, который не может выполниться немедленно? К примеру, работа с API, где мы отправляем запрос и должны ждать ответа. Чтобы смоделировать такую ситуацию, мы используем функцию setTimeout, которая вызывает функцию после заданного временного промежутка. Мы отсрочим выполнение функции на 500 миллисекунд, как будто бы это запрос к некому API. Теперь код будет выглядеть так:</p>
16
<p>Пока что все понятно. Но что, если функция first содержит некий код, который не может выполниться немедленно? К примеру, работа с API, где мы отправляем запрос и должны ждать ответа. Чтобы смоделировать такую ситуацию, мы используем функцию setTimeout, которая вызывает функцию после заданного временного промежутка. Мы отсрочим выполнение функции на 500 миллисекунд, как будто бы это запрос к некому API. Теперь код будет выглядеть так:</p>
17
<p>Неважно, понимаете ли вы сейчас, как работает setTimeout(). Основная идея - теперь мы отложили исполнение команды console.log(1) на 500 миллисекунд. И что теперь выведет наша программа?</p>
17
<p>Неважно, понимаете ли вы сейчас, как работает setTimeout(). Основная идея - теперь мы отложили исполнение команды console.log(1) на 500 миллисекунд. И что теперь выведет наша программа?</p>
18
<p>first(); second(); // 2 // 1</p>
18
<p>first(); second(); // 2 // 1</p>
19
<p>Хотя мы по-прежнему вызываем функцию first первой, ее вывод появился вторым, после вывода функции second. Но JavaScript не нарушает порядок вызова функций, он просто не дожидается ответа от функции first, а сразу двигается дальше - к функции second.</p>
19
<p>Хотя мы по-прежнему вызываем функцию first первой, ее вывод появился вторым, после вывода функции second. Но JavaScript не нарушает порядок вызова функций, он просто не дожидается ответа от функции first, а сразу двигается дальше - к функции second.</p>
20
<p>Поэтому нельзя просто вызывать функции в нужном порядке и надеяться, что они в любом случае выполнятся в том же порядке. Коллбэки же позволяют нам быть уверенными в том, что определенный код не начнет исполнение до того момента, пока другой код не завершит исполнение.</p>
20
<p>Поэтому нельзя просто вызывать функции в нужном порядке и надеяться, что они в любом случае выполнятся в том же порядке. Коллбэки же позволяют нам быть уверенными в том, что определенный код не начнет исполнение до того момента, пока другой код не завершит исполнение.</p>
21
<h2>Создаем коллбэк</h2>
21
<h2>Создаем коллбэк</h2>
22
<p>Во-первых, откройте консоль разработчика в Google Chrome (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J), либо свой IDE, либо просто<a>Repl.it</a>, и введите в консоли следующую функцию:</p>
22
<p>Во-первых, откройте консоль разработчика в Google Chrome (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J), либо свой IDE, либо просто<a>Repl.it</a>, и введите в консоли следующую функцию:</p>
23
<p>Мы создали функцию doHomework. Наша функция принимает одну переменную - название предмета, которым мы будем заниматься. Вызовите функцию, набрав следующий текст в консоли:</p>
23
<p>Мы создали функцию doHomework. Наша функция принимает одну переменную - название предмета, которым мы будем заниматься. Вызовите функцию, набрав следующий текст в консоли:</p>
24
<p>Теперь давайте добавим в определение функции еще один параметр, это и будет наш коллбэк. Затем вызовем ее, определив функцию-callback в качестве аргумента:</p>
24
<p>Теперь давайте добавим в определение функции еще один параметр, это и будет наш коллбэк. Затем вызовем ее, определив функцию-callback в качестве аргумента:</p>
25
<p>Если вы введете этот код в консоли, вы получите два алерта один за другим, в первом будет сообщение о том, что выполнение домашнего задания началось (Starting my math homework.), а во втором - что вы закончили выполнять задание (Finished my homework).</p>
25
<p>Если вы введете этот код в консоли, вы получите два алерта один за другим, в первом будет сообщение о том, что выполнение домашнего задания началось (Starting my math homework.), а во втором - что вы закончили выполнять задание (Finished my homework).</p>
26
<p>Однако коллбэки не обязательно должны быть определены при вызове функции. Они могут быть определены и в другом месте кода, например, так:</p>
26
<p>Однако коллбэки не обязательно должны быть определены при вызове функции. Они могут быть определены и в другом месте кода, например, так:</p>
27
<p>Таким образом, результат выполнения этого кода такой же, как и в предыдущем примере, однако сам код немного другой. Как вы видите, мы передали функцию alertFinished как аргумент в функцию doHomework при ее вызове.</p>
27
<p>Таким образом, результат выполнения этого кода такой же, как и в предыдущем примере, однако сам код немного другой. Как вы видите, мы передали функцию alertFinished как аргумент в функцию doHomework при ее вызове.</p>
28
<p>Перепишем пример вызова функции с setTimeout для последовательного выполнения функций:</p>
28
<p>Перепишем пример вызова функции с setTimeout для последовательного выполнения функций:</p>
29
<h2>Пример из реальной жизни</h2>
29
<h2>Пример из реальной жизни</h2>
30
<p>На прошлой неделе я опубликовал статью<a>"Создаем бота для Твиттера в 38 строк кода"</a>. Этот код работает благодаря API Твиттера. И когда мы делаем запрос к API, мы должны дождаться ответа до того, как начнем выполнять с этим ответом какие-то действия. Это прекрасный пример того, как в реальной жизни выглядит коллбэк. Вот как выглядит сам запрос:</p>
30
<p>На прошлой неделе я опубликовал статью<a>"Создаем бота для Твиттера в 38 строк кода"</a>. Этот код работает благодаря API Твиттера. И когда мы делаем запрос к API, мы должны дождаться ответа до того, как начнем выполнять с этим ответом какие-то действия. Это прекрасный пример того, как в реальной жизни выглядит коллбэк. Вот как выглядит сам запрос:</p>
31
<p>T.get просто значит, что мы выполняем get запрос к API Твиттера. В запросе три параметра: 'search/tweets' - это адрес (роут) запроса, params - наши параметры поиска и в конце передается анонимная функция-callback.</p>
31
<p>T.get просто значит, что мы выполняем get запрос к API Твиттера. В запросе три параметра: 'search/tweets' - это адрес (роут) запроса, params - наши параметры поиска и в конце передается анонимная функция-callback.</p>
32
<p>Коллбэк здесь нужен, потому что нам нужно дождаться ответа от сервера до того, как приступим к дальнейшему выполнению кода. Мы не знаем, успешным будет наш запрос или нет, поэтому после отправки параметров поиска на search/tweets через get-запрос, мы просто ждем. Как только Твиттер ответит, выполнится наша callback-функция. Твиттер отправит нам в качестве ответа или объект err (error - ошибка), или объект response. В коллбэке мы можем через if() проверить, был ли запрос успешным или нет, и затем действовать соответственно.</p>
32
<p>Коллбэк здесь нужен, потому что нам нужно дождаться ответа от сервера до того, как приступим к дальнейшему выполнению кода. Мы не знаем, успешным будет наш запрос или нет, поэтому после отправки параметров поиска на search/tweets через get-запрос, мы просто ждем. Как только Твиттер ответит, выполнится наша callback-функция. Твиттер отправит нам в качестве ответа или объект err (error - ошибка), или объект response. В коллбэке мы можем через if() проверить, был ли запрос успешным или нет, и затем действовать соответственно.</p>