2009-06-02 13 views
239

Gibt es eine Möglichkeit, weitere Daten in eine Callback-Funktion in jQuery zu übergeben?jQuery weitere Parameter in Callback übergeben

Ich habe zwei Funktionen, und ich mag den Rückruf an die $.post, beispielsweise sowohl in den resultierenden Daten des AJAX-Aufrufs zu übergeben, sowie einige benutzerdefinierten Argumenten

function clicked() { 
    var myDiv = $("#my-div"); 
    // ERROR: Says data not defined 
    $.post("someurl.php",someData,doSomething(data, myDiv),"json"); 
    // ERROR: Would pass in myDiv as curData (wrong) 
    $.post("someurl.php",someData,doSomething(data, myDiv),"json"); 
} 

function doSomething(curData, curDiv) { 

} 

ich sein will in der Lage, meine eigenen Parameter an einen Rückruf zu übergeben, sowie das vom AJAX-Aufruf zurückgegebene Ergebnis.

+13

Es ist erwähnenswert, dass jQuery.ajax() hat eine Kontexteinstellung seit ver 1.4 (http://jquery14.com/day-01/jquery-14) finden Sie ein Beispiel für seine Verwendung hier: http: // stackoverflow .com/questions/5097191/ajax-context-option/5097214 # 5097214 – russau

+0

Ich habe mein Problem mit der Rückgabe der Daten nach AJAX behoben und dann mache ich etwas. – Onaiggac

Antwort

323

Die Lösung ist, die Bindung von Variablen durch Schließung.


Als ein einfaches Beispiel, hier ist ein Beispiel Funktion, die eine Callback-Funktion, sowie ein Beispiel Callback-Funktion empfängt und ruft:

function callbackReceiver(callback) { 
    callback("Hello World"); 
} 

function callback(value1, value2) { 
    console.log(value1, value2); 
} 

Dies ist die Rückrufe und liefert ein einziges Argument . Jetzt möchten Sie ein zusätzliches Argument angeben, damit Sie den Callback in den Abschluss bringen.

callbackReceiver(callback);  // "Hello World", undefined 
callbackReceiver(function(value) { 
    callback(value, "Foo Bar"); // "Hello World", "Foo Bar" 
}); 

Oder einfacher ES6 Arrow Functions mit:

callbackReceiver(value => callback(value, "Foo Bar")); // "Hello World", "Foo Bar" 

Wie für Ihr konkretes Beispiel, ich habe die .post Funktion in jQuery nicht verwendet, sondern eine schnelle Prüfung der Dokumentation schlägt vor, die Rückruf sollte ein Funktionszeiger mit der folgenden Signatur sein:

function callBack(data, textStatus, jqXHR) {}; 

Deshalb denke ich, die Lösung wie folgt:

var doSomething = function(extraStuff) { 
    return function(data, textStatus, jqXHR) { 
     // do something with extraStuff 
    }; 
}; 

var clicked = function() { 
    var extraStuff = { 
     myParam1: 'foo', 
     myParam2: 'bar' 
    }; // an object/whatever extra params you wish to pass. 

    $.post("someurl.php", someData, doSomething(extraStuff), "json"); 
}; 

Was geschieht?

In der letzten Zeile ist doSomething(extraStuff) aufgerufen und das Ergebnis dieses Aufrufs ist ein Funktionszeiger.

Da extraStuff als Argument an doSomething übergeben wird, liegt es im Bereich der doSomething-Funktion.

Wenn extraStuff in der zurückgegebenen anonymen inneren Funktion von doSomething referenziert wird, wird es durch Schließen an das äußere Argument extraStuff der äußeren Funktion gebunden. Dies gilt auch, nachdem doSomething zurückgegeben wurde.

Ich habe die oben genannten nicht getestet, aber ich habe sehr ähnlichen Code in den letzten 24 Stunden geschrieben und es funktioniert wie ich beschrieben habe.

Sie können natürlich mehrere Variablen statt eines einzelnen 'extraStuff'-Objekts übergeben, abhängig von Ihren persönlichen Vorlieben/Codierungsstandards.

+0

Was ist der Zweck von 'var doSomething ='? Wie unterscheidet sich das nur davon, doSomething als eine Funktion zu deklarieren (dh Funktion doSomething (...) {}) –

+0

Es ist nicht wirklich anders. "Funktion foo() {};" ist syntaktischer Zucker für "var foo = function() {};". Das heißt, ich bevorzuge die Var-Syntax, besonders wenn Sie die Funktion als Daten weitergeben. – bradhouse

+6

Das stimmt nicht. Für diese beiden Funktionsdeklarationen gelten unterschiedliche Bereichsregeln. Das Verhalten ist je nach JS-Laufzeit sehr unterschiedlich (Browser lesen). Versuchen Sie auch, den in stacktrace/breakpoint in Firebug angezeigten Funktionsnamen zu vergleichen. –

0

tatsächlich, Ihr Code funktioniert nicht, weil, wenn Sie schreiben:

$.post("someurl.php",someData,doSomething(data, myDiv),"json"); 

Sie eine Anruffunktion platzieren als dritter Parameter anstelle einer Funktionsreferenz.

7

Sie können auch so etwas wie das folgende versuchen:

function clicked() { 

    var myDiv = $("#my-div"); 

    $.post("someurl.php",someData,function(data){ 
     doSomething(data, myDiv); 
    },"json"); 
} 

function doSomething(curData, curDiv) { 

} 
79

Wenn doSomething(data, myDiv) verwenden, können Sie die Funktion tatsächlich anrufen und nicht einen Verweis auf sie machen.

Sie können die Funktion doStomething entweder direkt übergeben, aber Sie müssen sicherstellen, dass sie die richtige Signatur hat.

Wenn Sie so etwas tun wollen, wie es ist, können Sie seinen Anruf in eine anonyme Funktion umbrechen.

function clicked() { 
    var myDiv = $("#my-div"); 
    $.post("someurl.php",someData, function(data){ 
     doSomething(data, myDiv) 
    },"json"); 
} 

function doSomething(curData, curDiv) { 
    ... 
} 

Innerhalb des anonymen Funktionscodes können Sie die im umschließenden Bereich definierten Variablen verwenden. So funktioniert das JavaScript-Scoping.

+7

Dies ist die beste Lösung IMO, aus Gründen der Klarheit. Keine zusätzliche Funktion 'return function (...) {...}' innerhalb der 'doSomething'-Funktion. Ich fand ein anderes klares Beispiel des gleichen Konzeptes hier: http://theelitist.net/passing-additional-arguments-to-a-callback-function-in-javascript –

+4

Ich denke, dass es ein Problem mit diesem gibt. Wenn sich Ihre zusätzlichen Daten (in diesem Fall myDiv) ändern, bevor der Callback ausgelöst wird, erhalten Sie den neuen Wert und nicht den alten! In meinem Fall habe ich Ajax-Aufrufe für Objekte in einem Array abgefeuert, und als der erste Aufruf von success() ausgeführt wurde, dachte es, dass es beim letzten Element erfolgreich war, als es das erste war! Bradhouses Antwort funktionierte für mich. – Chris

+0

@Chris Ja, erfasste Variablen können in Javascript geändert werden. Wenn Sie dieses Verhalten nicht möchten, müssen Sie eine explizite Funktion erstellen, um den Wert zu erfassen. Das gebräuchlichste Idiom ist eine selbstausführende Funktion '(function (myDiv) {...}) (myDiv)', um die Variable 'myDiv' einzufangen. Dies ist implizit in @ Bradhouse Antwort getan. –

5

können Sie einen Verschluss von JavaScript verwenden:

function wrapper(var1, var2,....) // put here your variables 
{ 
    return function(data, status) 
    { 
    //Handle here results of call 
    } 
}; 

und wenn Sie tun können:

$.post("someurl.php",data,wrapper(var1, var2, etc...),"html"); 
3

Ich habe einen Fehler in der letzten meiner Post gemacht. Dies funktioniert Beispiel dafür, wie zusätzliches Argument in Callback-Funktion zu übergeben: Die

function custom_func(p1,p2) { 
    $.post(AJAX_FILE_PATH,{op:'dosomething',p1:p1}, 
     function(data){ 
      return function(){ 
       alert(data); 
       alert(p2); 
      }(data,p2) 
     } 
    ); 
    return false; 
} 
+1

Sie sollten entweder Ihre ursprüngliche Antwort bearbeiten oder löschen, bevor Sie eine neue hinzufügen. – Blazemonger

17

In der heutigen Welt gibt es eine andere Antwort, die sauberer ist und von einer anderen Stack-Überlauf Antwort genommen:

function clicked() 
{ 
    var myDiv = $("#my-div"); 

    $.post("someurl.php", {"someData": someData}, $.proxy(doSomething, myDiv), "json"); 
} 

function doSomething(data) 
{ 
    // this will be equal to myDiv now. Thanks to jQuery.proxy(). 
    var $myDiv = this; 

    // doing stuff. 
    ... 
} 

Hier ist die Original Frage und Antwort: jQuery HOW TO?? pass additional parameters to success callback for $.ajax call?

0

Als Nachtrag zu b01's answer wird das zweite Argument von $.proxy oft verwendet, um diezu bewahrenReferenz. Zusätzliche Argumente, die an $.proxy übergeben wurden, werden teilweise auf die Funktion angewendet und mit Daten vorbefüllt. Beachten Sie, dass alle Argumente $.post an die Callback übergibt am Ende angewendet werden, so doSomething diejenigen am Ende der Argumentliste haben sollte:

erlaubt
function clicked() { 
    var myDiv = $("#my-div"); 
    var callback = $.proxy(doSomething, this, myDiv); 
    $.post("someurl.php",someData,callback,"json"); 
} 

function doSomething(curDiv, curData) { 
    //"this" still refers to the same "this" as clicked() 
    var serverResponse = curData; 
} 

Dieser Ansatz auch mehrere Argumente gebunden sein, um den Rückruf:

47

Es ist eigentlich einfacher als jeder macht es klingen ... vor allem, wenn Sie die $.ajax({}) Basis-Syntax vs.eine der Hilfsfunktionen.

passieren einfach das key: value Paar, wie Sie es auf ein beliebiges Objekt, wenn Sie Setup Ihre Ajax-Request ... (weil $(this) Kontext noch nicht geändert hat, ist es immer noch der Auslöser für die bind Anruf oben)

Einer der Gründe, warum dies besser als die Einstellung der Var ist, ist, dass die Variable global ist und als solche überschreibbar ... Wenn Sie 2 Dinge haben, die Ajax-Aufrufe auslösen können, könnten Sie sie theoretisch schneller als auslösen Der Ajax-Anruf antwortet, und Sie haben den Wert für den zweiten Anruf an den ersten übergeben. Mit dieser Methode würde das nicht passieren (und es ist auch ziemlich einfach zu benutzen).

+2

das ist genau das, was ich gesucht habe. Ich wusste nicht, wann Sie den Datentyp als json angegeben haben, er analysierte die Antwort automatisch für Sie. That nice (: – Rooster

+1

Klingt nach dem besten Weg, um zusätzliche Parameter zu Callback an mich zu übergeben. Ich würde mich interessieren, wenn jemand einen Nachteil mit diesem Ansatz sieht? Einfachste und elegant. Danke! –

+0

"_the var ist global und als solche, überschreibbar_" Es ist nicht, wenn Sie es innerhalb einer Funktion deklarieren, die auch viel lesbarer ist als die obige Lösung.Verwenden Sie _closures_ ist ein sauberer Ansatz - siehe meine Antwort hier: http://StackOverflow.com/a/18570951/885464 –

3

Los geht's einfach! :)

$.ajax({ 
    url: myUrl, 
    context: $this, // $this == Current $element 
    success: function(data) { 
     $.proxy(publicMethods.update, this)(data); // this == Current $element 
    } 
}); 
2

Eine allgemeine Lösung für asynchrone Anfragen zu senden mit der .ajax() jQuery API und Schließungen, um zusätzliche Parameter an die Callback-Funktion übergeben:

function sendRequest(method, url, content, callback) { 
    // additional data for the callback 
    var request = { 
     method: method, 
     url: url 
    }; 

    $.ajax({ 
     type: method, 
     url: url, 
     data: content 
    }).done(function(data, status, xhr) { 
     if (callback) callback(xhr.status, data, request); 
    }).fail(function(xhr, status) { 
     if (callback) callback(xhr.status, xhr.response, request); 
    }); 
}; 
1

Für mich und andere Neulinge, die gerade in Berührung gekommen sind mit Javascript,
Ich denke, dass die Closeure Solution ist ein wenig zu verwirrend.

Während ich das gefunden habe, können Sie einfach so viele Parameter wie Sie wollen jeden Ajax Callback mit jquery übergeben.

Hier sind zwei einfachere Lösungen.

erste, die @zeroasterisk oben erwähnt wird, beispielsweise:

var $items = $('.some_class'); 
$.each($items, function(key, item){ 
    var url = 'http://request_with_params' + $(item).html(); 
    $.ajax({ 
     selfDom  : $(item), 
     selfData : 'here is my self defined data', 

     url   : url, 
     dataType : 'json', 
     success  : function(data, code, jqXHR){ 
      // in $.ajax callbacks, 
      // [this] keyword references to the options you gived to $.ajax 
      // if you had not specified the context of $.ajax callbacks. 
      // see http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings context 
      var $item = this.selfDom; 
      var selfdata = this.selfData; 
      $item.html(selfdata); 
      ... 
     } 
    }); 
}); 

zweite, passieren selbstdefinierte-Daten, indem sie in die XHR object Zugabe, die in dem ganzen ajax-Anfrage- existiert Antwortzeitspanne.

var $items = $('.some_class'); 
$.each($items, function(key, item){ 
    var url = 'http://request_with_params' + $(item).html(); 
    $.ajax({ 
     url   : url, 
     dataType : 'json', 
     beforeSend : function(XHR) { 
      // 为了便于回调,把当前的 jquery对象集存入本次 XHR 
      XHR.selfDom = $(item); 
      XHR.selfData = 'here is my self defined data'; 
     }, 
     success  : function(data, code, jqXHR){ 
      // jqXHR is a superset of the browser's native XHR object 
      var $item = jqXHR.selfDom; 
      var selfdata = jqXHR.selfData; 
      $item.html(selfdata); 
      ... 
     } 
    }); 
}); 

Wie Sie diese beiden Lösungen sehen kann, hat den Nachteil, dass: man ein wenig mehr Code schreiben müssen, jedes Mal, als nur schreiben:

$.get/post (url, data, successHandler); 

mehr über lesen $ Schnipsel: http://api.jquery.com/jquery.ajax/

1
$(document).on('click','[action=register]',function(){ 
    registerSocket(registerJSON(),registerDone,second($(this))); 
}); 

function registerSocket(dataFn,doneFn,second){ 
       $.ajax({ 
         type:'POST', 
         url: "http://localhost:8080/store/public/register", 
         contentType: "application/json; charset=utf-8", 
         dataType: "json", 
         data:dataFn 
       }).done ([doneFn,second]) 
        .fail(function(err){ 
          console.log("AJAX failed: " + JSON.stringify(err, null, 2)); 
         }); 
} 

function registerDone(data){ 
    console.log(JSON.stringify(data)); 
} 
function second(element){ 
    console.log(element); 
} 

Secondary Art und Weise:

function socketWithParam(url,dataFn,doneFn,param){ 
    $.ajax({ 
    type:'POST', 
    url:url, 
    contentType: "application/json; charset=utf-8", 
    headers: { 'Authorization': 'Bearer '+localStorage.getItem('jwt')}, 
    data:dataFn 
    }).done(function(data){ 
     doneFn(data,param); 
    }) 
    .fail(function(err,status,xhr){ 
    console.log("AJAX failed: " + JSON.stringify(err, null, 2)); 
    }); 
} 

$(document).on('click','[order-btn]',function(){ 
    socketWithParam(url,fakeDataFn(),orderDetailDone,secondParam); 
}); 

function orderDetailDone(data,param){ 
    -- to do something -- 
} 
0

Wenn jemand noch hier kommt, das ist mein nehmen:

$('.selector').click(myCallbackFunction.bind({var1: 'hello', var2: 'world'})); 

function myCallbackFunction(event) { 
    var passedArg1 = this.var1, 
     passedArg2 = this.var2 
} 

Was hier passiert, nachdem sie auf die Callback-Funktion zu binden, es innerhalb der Funktion als this zur Verfügung stehen wird.

Diese Idee kommt davon, wie React die bind Funktionalität verwendet.

Verwandte Themen