Ознайомлення з функціями зворотного дзвінка в JavaScript


163

Я розумію перехід функції до іншої функції як зворотний виклик і його виконання, але я не розумію найкращої реалізації для цього. Я шукаю дуже базовий приклад, наприклад:

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, якщо я повертаю новий зворотний виклик (), він працює і виконує анонімну функцію, але це не здається правильним підходом до мене.


Правильно в якому сенсі? Зазвичай зворотні виклики використовуються для обробників подій - найчастіше дзвінки Ajax, які є асинхронними - в основному це те, де ви не знаєте, коли (або якщо) настане відповідь.
клент

2
до речі аргументи такі як масив, але не масив, тому ви не можете зробити argument.length, але ви можете перетворити його в масив, використовуючи метод зрізу ...
paul

1
@paul, хоча ви маєте рацію, що argumentsце не масив, ви все ще можете посилатися на його довжину як arguments.length- спробуйте. Це властивість посилається на кількість фактично переданих аргументів, а не обов'язково на кількість параметрів підпису функції.
hotshot309

Відповіді:


132

Можна просто сказати

callback();

Крім того, ви можете використовувати callметод, якщо ви хочете відрегулювати значення thisзворотного дзвінка.

callback.call( newValueForThis);

Всередині функції thisбуло б все, що newValueForThisє.


91

Ви повинні перевірити, чи існує зворотний виклик і чи виконується функція:

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

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


Чому ви кидаєте callbackна рядок, а потім перевіряєте його тип? Чи підвищить це ефективність? Це як перевірка типу, перевірка повернення перетвореного булевого значення true, а потім ще раз перевірка його типу та тестування на рядок ... Чи можете ви пояснити, чому?
головний

Мені цікаво, чому вам потрібно перше твердження про зворотний виклик ... це перевірити нульове чи невизначене? Ви б цього не typeof(callback)досягли? typeof(null) === "Object",typeof("undefined") === "undefined"
PJH

1
Коротке замикання І. Якщо зворотного дзвінка не існує, не переймайтеся обчисленням його типу. Хоча ти маєш рацію. Це не потрібно для typeof (), але я зроблю jsperf і побачу, чи варто цього короткого замикання.
arunjitsingh

@headacheCoder - callbackне передається в рядок, його тип перевіряється, щоб перевірити, чи є вона функцією, перш ніж її викликати. Код, імовірно, приймає callbackяк аргумент і не впевнений, що аргумент має тип дзвінка - або, можливо, аргументи є різного типу в спробі надати форму поліморфізму, коли код може по-різному реагувати на різні typeofаргументи.
LeeGee

34

Існує 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, argument_1, argument_2);
  3. callback.apply (some_object, [argument_1, argument_2]);

Вибраний спосіб залежить від того:

  1. У вас аргументи зберігаються в масиві або як окремі змінні.
  2. Ви хочете викликати цю функцію в контексті якогось об'єкта. У цьому випадку використання ключового слова "це" у цьому зворотному дзвінку посилатиметься на об'єкт, переданий як аргумент у call (), або застосувати (). Якщо ви не хочете передавати контекст об'єкта, використовуйте null або undefined. В останньому випадку глобальний об’єкт буде використовуватися для "цього".

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


6

Відкликання дзвінків - це сигнали, а "нове" - про створення об'єктів.

У цьому випадку було б ще доцільніше виконати просто "callback ();" ніж "повернути новий зворотний виклик ()", оскільки ви все одно нічого не робите зі значенням повернення.

(І аргумент argument.length == 3 дійсно незграбний, fwiw, краще перевірити, чи існує парам зворотного виклику і є функцією.)


6

належною реалізацією було б:

if( callback ) callback();

це робить параметр зворотного виклику необов’язковим ..


Що робити, якщо аргумент зворотного виклику не є функцією?
Які Кляйн

2

Ви можете використовувати:

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

Ось основний приклад, який пояснює callback()функцію в JavaScript:

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);
});

JSFiddle


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.