Получение лучшего понимания функций обратного вызова в JavaScript - PullRequest
163 голосов
/ 27 января 2009

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

var myCallBackExample = {
    myFirstFunction : function( param1, param2, callback ) {
        // Do something with param1 and param2.
        if ( arguments.length == 3 ) {
            // Execute callback function.
            // What is the "best" way to do this?
        }
    },
    mySecondFunction : function() {
        myFirstFunction( false, true, function() {
            // When this anonymous function is called, execute it.
        });
    }
};

В myFirstFunction, если я возвращаю новый callback (), тогда он работает и выполняет анонимную функцию, но мне это не кажется правильным.

Ответы [ 8 ]

131 голосов
/ 27 января 2009

Вы можете просто сказать

callback();

В качестве альтернативы вы можете использовать метод call, если хотите настроить значение this в обратном вызове.

callback.call( newValueForThis);

Внутри функции this будет таким, каков newValueForThis.

89 голосов
/ 22 марта 2011

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

if (callback && typeof(callback) === "function") {
    // execute the callback, passing parameters as necessary
    callback();
}

Многие библиотеки (jQuery, dojo и т. Д.) Используют аналогичный шаблон для своих асинхронных функций, а также node.js для всех асинхронных функций (nodejs обычно передает error и data в обратный вызов). Просмотр их исходного кода поможет!

34 голосов
/ 27 января 2009

Существует 3 основных варианта выполнения функции:

var callback = function(x, y) {
    // "this" may be different depending how you call the function
    alert(this);
};
  1. обратный вызов (аргумент_1, аргумент_2);
  2. callback.call (some_object, аргумент_1, аргумент_2);
  3. callback.apply (some_object, [аргумент_1, аргумент_2]);

Метод, который вы выберете, зависит от того:

  1. У вас есть аргументы, хранящиеся в массиве или в виде отдельных переменных.
  2. Вы хотите вызвать эту функцию в контексте какого-либо объекта. В этом случае использование ключевого слова this в этом обратном вызове будет ссылаться на объект, переданный в качестве аргумента в call () или apply (). Если вы не хотите передавать контекст объекта, используйте null или undefined. В последнем случае глобальный объект будет использоваться для «этого».

Документы для Function.call , Function.apply

6 голосов
/ 03 марта 2011

правильная реализация будет:

if( callback ) callback();

это делает параметр обратного вызова необязательным ..

6 голосов
/ 27 января 2009

Обратные вызовы относятся к сигналам, а «новое» - к созданию экземпляров объекта.

В этом случае было бы еще более уместно выполнить просто "callback ();" чем "return new callback ()", потому что вы все равно ничего не делаете с возвращаемым значением.

(И тест arguments.length == 3 действительно неуклюж, fwiw, лучше проверить, что параметр обратного вызова существует и является функцией.)

2 голосов
/ 21 декабря 2015

Вы можете использовать:

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

приведенный ниже пример является немного более полным:

function mySandwich(param1, param2, callback) {
alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
var sandwich = {toppings: [param1, param2]},
    madeCorrectly = (typeof(param1) === "string" && typeof(param2) === "string") ? true : false;
if (callback && typeof(callback) === "function") {  
    callback.apply(sandwich, [madeCorrectly]);  
  }  
}  

mySandwich('ham', 'cheese', function(correct) {
if(correct) {
    alert("Finished eating my " + this.toppings[0] + " and " + this.toppings[1] + " sandwich.");
} else {
    alert("Gross!  Why would I eat a " + this.toppings[0] + " and " + this.toppings[1] + " sandwich?");
  }
});
1 голос
/ 24 марта 2015

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

var x=0;

function testCallBack(param1, param2, callback) {
    alert('param1= ' + param1 + ', param2= ' + param2+' X='+x);
    if (callback && typeof(callback) === "function") {
        x+=1;
        alert("Calla Back x= "+x);
        x+=1;
        callback();
    }
}


testCallBack('ham', 'cheese',function(){
alert("Function X= "+x);
});
1 голос
/ 06 апреля 2011
function checkCallback(cb)
{
    if(cb || cb!='')
    {
        if(typeof window[cb] === 'undefined') alert('Callback function not found.');
        else window[cb].call(this,Arg1, Arg2);
    }
}
...