2009-01-27 17 views
159

Rozumiem przekazywanie funkcji do innej funkcji jako wywołania zwrotnego i wykonanie jej, ale nie rozumiem najlepszej implementacji, aby to zrobić. Szukam bardzo prosty przykład coś takiego:Lepsze zrozumienie funkcji wywołania zwrotnego w JavaScript

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

W myFirstFunction, jeśli mam wrócić zwrotnego (nowy), to działa i wykonuje funkcję anonimową, ale to nie wydaje się prawidłowe podejście do mnie.

+0

Correct w jakim sensie? Zwykle wywołania zwrotne są używane do obsługi zdarzeń - w szczególności wywołania Ajax, które są asynchroniczne - w zasadzie rzeczy, w których nie wiadomo, kiedy (lub jeśli) pojawi się odpowiedź. – cletus

+2

przy okazji argumenty są tablicowe, ale nie tablicowe, więc nie można zrobić argumentu.length, ale można go przekonwertować na tablicę za pomocą metody slice ... – paul

+1

@paul, chociaż masz rację, że 'argumenty' nie są array, nadal możesz odwoływać się do jego długości jako 'arguments.length' - spróbuj. Ta właściwość odnosi się do liczby argumentów faktycznie przekazanych, a niekoniecznie do liczby parametrów w sygnaturze funkcji. – hotshot309

Odpowiedz

129

Można tylko powiedzieć

callback(); 

Alternatywnie możesz użyć metody call, jeśli chcesz zmienić wartość this w ramach wywołania zwrotnego.

callback.call(newValueForThis); 

Wewnątrz funkcji this byłoby cokolwiek newValueForThis jest.

6

Oddzwanianie dotyczy sygnałów, a "nowe" dotyczy tworzenia wystąpień obiektu.

W tym przypadku byłoby jeszcze bardziej odpowiednie wykonanie tylko "callback();" niż "return new callback()", ponieważ i tak nic nie robisz z wartością zwracaną.

(a test arguments.length == 3 jest naprawdę niezgrabne, FWIW, lepiej sprawdzić, zwrotna param istnieje i jest funkcją.)

34

są 3 główne możliwości, aby wykonać funkcję:

var callback = function(x, y) { 
    // "this" may be different depending how you call the function 
    alert(this); 
}; 
  1. zwrotnego (ARGUMENT_1, ARGUMENT_2);
  2. callback.call (some_object, argument_1, argument_2);
  3. callback.apply (some_object, [argument_1, argument_2]);

Wybór metody zależy od tego, czy:

  1. masz argumentów zapisanych w tablicy lub jako odrębne zmienne.
  2. Chcesz wywołać tę funkcję w kontekście jakiegoś obiektu. W tym przypadku użycie słowa kluczowego "this" w tym wywołaniu zwrotnym będzie odwoływać się do obiektu przekazanego jako argument w wywołaniu() lub apply(). Jeśli nie chcesz przekazywać kontekstu obiektu, użyj wartości null lub undefined. W tym drugim przypadku obiekt globalny zostanie użyty dla "tego".

Docs dla Function.call, Function.apply

6

właściwa realizacja będzie:

if(callback) callback(); 

To sprawia, że ​​parametr callback opcjonalne ..

+0

Co się stanie, jeśli argument wywołania zwrotnego nie jest funkcją? –

88

Należy sprawdzić, czy zwrotna istnieje i jest wykonywalny funkcja:

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

Wiele bibliotek (jQuery, dojo, etc.) używać podobny wzór dla swoich asynchronicznych funkcji, jak również węzeł .js dla wszystkich funkcji asynchronicznych (nodejs zwykle przekazuje error i data do wywołania zwrotnego). Pomocne byłoby zajrzenie do ich kodu źródłowego!

+0

Dlaczego rzucasz 'callback' na ciąg, a następnie sprawdzasz jego typ? Czy to zwiększy wydajność? To jest jak sprawdzanie typu, sprawdzanie, czy skonwertowana wartość boolowska zwraca true, a następnie ponowne sprawdzenie jej typu i przetestowanie na łańcuchu ... Czy możesz wyjaśnić, dlaczego? – headacheCoder

+0

Jestem ciekawy, dlaczego potrzebujesz pierwszego asercji dla oddzwonienia ... czy to sprawdzić wartość null czy undefined? Czy 'typeof (callback)' nie osiągnie tego dla ciebie? 'typeof (null) ===" Object "', 'typeof (" undefined ") ===" undefined "' – PJH

+1

Zwarcie AND. Jeśli wywołanie zwrotne nie istnieje, nie zawracaj sobie głowy obliczaniem jego typu. Chociaż masz rację. Nie jest potrzebna z typeof(), ale zrobię jsperf i zobaczę, czy to jest warte spięcia. – arunjitsingh

1
function checkCallback(cb) 
{ 
    if(cb || cb!='') 
    { 
     if(typeof window[cb] === 'undefined') alert('Callback function not found.'); 
     else window[cb].call(this,Arg1, Arg2); 
    } 
} 
1

Możesz rzucić okiem na ten link i dodać dla ciebie podstawowy przykład wyjaśniający funkcję oddzwaniania w 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); 
}); 
2

Można użyć:

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

Poniższy przykład jest trochę bardziej wszechstronny:

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?"); 
    } 
}); 
Powiązane problemy