Callback-функции в JavaScript

Если вы не имеете большого опыта работы с JavaScript, но уже использовали JQuery, то, возможно, вы уже использовали функции обратного вызова. Но, может быть, вы не до конца понимаете, как они работают или как они устроены?

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

 

 

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

Статья из Wikipedia говорит:

Ссылка на исполняемый код, или на фрагмент исполняемого кода, который передается в качестве аргумента другого кода.

Далее идет простой пример callback-функции, взятый из JQuery:

$('#element').fadeIn('slow', function() {
    // callback function
});

Здесь происходит вызов JQuery метода fadeIn(). Этот метод принимает 2 аргумента: скорость fade-in анимации и функция обратного вызова (необязательный параметр). В этой функции вы можете писать все, что угодно.

Когда fadeIn() метод завершится, callback-функция начнет выполняться, если она задана. В зависимости от скорости анимации, вы можете выбрать задержку до начала выполнения функции. Прочитать более подробней о callback-функциях вы можете здесь.

 

 Как писать callback-функции

Если вы пишете свои собственные функции или методы, вам могут понадобиться функции обратного вызова. Далее приведены простые примеры callback-функций:

function mySandwich(param1, param2, callback) {
    alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
    callback();
}

mySandwich('ham', 'cheese', function() {
    alert('Finished eating my sandwich.');
});

Здесь мы видим функцию mySandwich, которая принимает 3 параметра. Третий параметр — функция обратного вызова. Когда функция выполняется, она выводит на экран сообщение с переданными значениями. Затем выполняется функция обратного вызова.

Обратите внимание, что фактический параметр mySandwich является просто «callback» (без скобок), но потом, когда мы вызываем callback, мы используем круглые скобки.

Сама функция обратного вызова определена в третьем параметре (function() {…}). Этот код имеет в себе вызов функции alert(), которая говорит, что callback-функция вызвана.

 

Создание опциональной функции обратного вызова

Все функции обратного вызова в JQuery опциональны, т.е. необязательны. Это означает, что метод, принимающий callback-функцию не будет возвращать ошибку, если функция не передана. В простом примере ниже, будет выведена ошибка, если мы вызовем функцию mySandwich без передачи функции «callback»:

function mySandwich(param1, param2, callback) {
    alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
    callback();
}

mySandwich('ham', 'cheese');

Действие можно увидеть здесь. Если вы откроете свой инструмент разработки, то вы увидите ошибку, которая говорит, что «undefined is not a function» (или что-то подобное), которое показывается после выполнения alert сообщения.

Чтобы сделать callback-функцию необязательной, мы может сделать так:

function mySandwich(param1, param2, callback) {
    alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
    if (callback) {
        callback();
    }
}

mySandwich('ham', 'cheese');

Теперь callback-функция будет вызвана лишь при условии, что она существует. Никакой ошибки теперь не будет. Протестировать можно здесь.

 

 Убедитесь, что callback является функцией

Наконец, вы можете узнать, что третий аргумент является функцией, если сделаете так:

function mySandwich(param1, param2, callback) {
    alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
    if (callback && typeof(callback) === "function") {
        callback();
    }
}

mySandwich('ham', 'cheese', 'vegetables');

Заметьте, что мы использовали typeof оператор для проверки типа значения callback параметра. В данном примере мы передали в качестве третьего параметра не функцию, а строку, но ошибки не возникает, т.к. у нас стоит проверка на функцию.

 

 Примечание о времени

Не всегда функция может выполниться тогда, когда нужно. Например, если функция включена в какой-нибудь асинхронный запрос (ajax или анимацию), то callback-функция будет вызвана после начала асинхронного запроса и, возможно, завершиться раньше асинхронного запроса.

Вот пример, в котором используется JQuery animate метод:

function mySandwich(param1, param2, callback) {
    alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);

    $('#sandwich').animate({
        opacity: 0
    }, 5000, function() {
        // Animation complete.
    });

    if (callback && typeof(callback) === "function") {
        callback();
    }
}

mySandwich('ham', 'cheese', function() { 
    alert('Finished eating my sandwich.');
});

Демонстрация здесь.

Заметьте, что хотя callback-функция расположена после кода анимации, функция обратного вызова выполнится намного раньше, чем закончится анимация. Решить проблему очень просто: мы должны поместить функцию обратного вызова внутрь animate метода (туда, где написано «//Animation complete»).

 

 Хотите что-нибудь добавить?

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

 

Спасибо за внимание!

 

 

 

Автор статьи: Alex. Категория: JavaScript
Дата публикации: 21.05.2013