При изучении JavaScript необходимость
в использовании функций возврата возникает достаточно часто. Они могут казатся
странными и непонятными для новичков, но даже на этом этапе очень важно понять как они работают. В будущем эти
знания позволят использовать язык намного эффективней. В данной статье я
попытаюсь рассказать о базовых принципах и продемонстрировать с помощью
простейших примеров.
Что такое функция возврата?
Простой
ответ: Функция возврата – это функция которая выполняется
когда другая функция (как правило асинхронная) завершило свое выполнение.
Более
сложный ответ: В JavaScript функции – это объекты.
Поэтому функции могут использовать другие функции в качестве своих аргументов и
могут возвращать функции. Такие функции называются функциями верхнего порядка.
А функции которые передаются в качестве аргументов и вызываются последовательно
функцией которая ее получила называются функциями возврата.
Но это все слова, давайте
взглянем на пример.
Зачем нам нужны функции возврата?
По одной очень важной причине –
JavaScript –
это язык построенный на событиях. Это значит, что вместо того что бы ждать ответа,
JavaScript продолжит
выполнение и будет прослушивать другие события. Давайте обратимся к примеру.
function first(){
console.log(1);
}
function second(){
console.log(2);
}
first();
second();
Как вы можете предположить,
функция first выполнится
первой, а функция second – второй. Это
отражает и вывод на консоли.
// 1
// 2
Пока все хорошо.
Но что если первая функция
будет иметь какойто код который не будет выполнятся сиюминутно? Например,
запрос API когда
нам нужно отослать запрос и дождаться ответа? Это можно симулировать с помощью
функции setTimeout,
которая является встроеным средством JavaScript и позволяет
выполнять некоторый код по прошествии заданного времени. Мы добавим задурждку в
500 мс к нашему коду, что этого что бы сэмулировать запрос API. Наш новый код
теперь будет выглядеть так:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
Сейчас не важно если
вы не совсем понимаете как работает функция setTimeout() (хотя
я думаю что поинтересоваться стоит, например почитать здесь).
Суть здесь в том, что мы добавили задержку 500 мс к вызову console.log(1);.
Итак, что же теперь мы получили?
first();
second();
// 2
// 1
Несмотря на то, что мы
вызываем функцию first()
первой, в логах результата мы ее видим посде функции second().
Тут дело не в том, что JavaScript не
выполняет наши функции в том порядке, в каком мы хотим, а просто JavaScript не
ожидает получения ответа от first()
и переходит к выполнению second().
Почему я это вам показываю?
Потому что вы не можете просто вызвать функции
одну за другой и надеятся что они выполнятся именно в том же порядке. Функции возврата
предоставляют возможность выполнить быть увереным в том, что ваш код не будет
выполнен до завершения некоторого
другого кода.
Создаем функцию возврата
Ладно, хватит
болтать, давайте создадим функцию возврата!
Во первых, откройте консоль разработчика в браузере (вы можете открыть ее с помощью Ctrl + Shift + J на Windows/Linux или Cmd + Option + J на Mac). После этого напишите вот такую функцию в консоли:
function doHomework(subject) {
alert(`Starting my ${subject}
homework.`);
}
Выше мы создали функцию doHomework. Она принимает один аргумент – заголовок с которым
мы работаем. Вызовите вышу функцию, для этого напечатайте в консоли следующее:
doHomework('math');
// Отобразит
сообщение:
Starting my math homework.
Теперь давайте ее немного
улучшим – в качестве последнего параметра функции doHomework()
передадим функцию возврата. Сама функция определена при вызове doHomework()
в качестве второго аргумента.
function doHomework(subject,
callback) {
alert(`Starting my ${subject}
homework.`);
callback();
}
doHomework('math', function() {
alert('Finished my homework');
});
Как вы увидите, если вы
создадите такой код, то получите два сообщения: вначале сообщение ‘Starting
homework’, а затем ‘Finished
homework’.
Но функции возврата не всегда получают
определение при вызове. Они могут быть объявлены в другом месте, как в этом
примере:
function doHomework(subject,
callback) {
alert(`Starting my ${subject}
homework.`);
callback();
}
function alertFinished(){
alert('Finished my homework');
}
doHomework('math',
alertFinished);
Результат выполнения этого
кода абсолютно такой же как и в предыдущем случае, но код здесь написан немного
по другому. Как вы можете видеть мы передали функцию alertFinished в качестве аргумента при
вызове doHomework().
Реальный пример
На прошлой неделе я
опубликовал статью как
создать бот для Твитера в 38 строках
кода. И единственная причина, почему код из той статьи работал – это Twitter API. Когда вы
делаете запрос в API,
то вы должны подождать ответа прежде чем можете с ним что нибудь делать. Это
прекрасный пример использованися функций возврата. Вот примерно так выглядит
запрос:
T.get('search/tweets',
params, function(err,
data, response) {
if(!err){
// This is where the magic will happen
} else {
console.log(err);
}
});
- T.get
просто значит что мы создаем запрос GET для
twitter.
- Три параметра в запросе:
‘search/tweets’ определяет маршрут
нашего запроса,
params параметры
поиска и третий параметр – анонимная функция которая является функцией
возврата.
Функция возврата
важна потому что нам нужно подождать ответ с сервера, и только после этого двигаться
дальше. Мы не знаем будут ли наши запросы к API успешны или нет, поэтому мы ждем. Как только Twitter ответил,
вызывается наша функция. Twitter либо сообщит об
ошбике с помощью объекта err (error),
или пришлет объект response.
В нашей функции мы можем использовать простой if() для того что бы
определить был ли запрос успешным, и после этого обрабатывать ответ
сообтветсвующим образом.
Вы сделали это
Отличная работа! Теперь вы понимаете
что такое функция возврата и как ей пользоваться. Но это лишь маленькая часть
айсберга по работе с функциями возврата, еще многому нужно научиться! Если у
вас есть вопросы или коментарии – оставляйте их ниже. Я буду рад их услышать.
Комментариев нет:
Отправить комментарий