jQuery passa più parametri in callback

C’è un modo per passare più dati in una funzione di callback in jQuery?

Ho due funzioni e voglio il callback su $.post , per esempio, per passare sia i dati risultanti della chiamata AJAX, sia alcuni argomenti personalizzati

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

Voglio essere in grado di passare i miei parametri a una richiamata, nonché il risultato restituito dalla chiamata AJAX.

La soluzione è il legame delle variabili attraverso la chiusura.


Come esempio di base, ecco una funzione di esempio che riceve e chiama una funzione di callback, oltre a una funzione di callback di esempio:

 function callbackReceiver(callback) { callback("Hello World"); } function callback(value1, value2) { console.log(value1, value2); } 

Questo chiama il callback e fornisce un singolo argomento. Ora si desidera fornire un argomento aggiuntivo, in modo da avvolgere il callback in chiusura.

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

O, più semplicemente usando ES6 Arrow Functions :

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

Per quanto riguarda il tuo esempio specifico, non ho usato la funzione .post in jQuery, ma una scansione veloce della documentazione suggerisce che la richiamata dovrebbe essere un puntatore a funzione con la seguente firma:

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

Quindi penso che la soluzione sia la seguente:

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

Che cosa sta succedendo?

Nell’ultima riga, doSomething(extraStuff) viene richiamato e il risultato di tale richiamo è un puntatore a funzione .

Poiché extraStuff viene passato come argomento per fare qualcosa, si trova nell’ambito della funzione doSomething .

Quando extraStuff viene referenziato nella funzione interna anonima restituita di doSomething , è vincolato dalla chiusura all’argomento extraStuff della funzione esterna. Questo è vero anche dopo che doSomething è tornato.

Non ho provato quanto sopra, ma ho scritto codice molto simile nelle ultime 24 ore e funziona come ho descritto.

Ovviamente è ansible passare più variabili anziché un singolo object “extraStuff” a seconda delle preferenze personali / degli standard di codifica.

Quando si utilizza doSomething(data, myDiv) , si chiama effettivamente la funzione e non si fa riferimento ad essa.

È ansible passare direttamente la funzione doStomething ma è necessario assicurarsi che abbia la firma corretta.

Se si desidera mantenere DoSomething così com’è, è ansible racchiudere la chiamata in una funzione anonima.

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

All’interno del codice funzione anonimo, è ansible utilizzare le variabili definite nell’ambito di inclusione. Questo è il modo in cui funziona lo scoping di Javascript.

In realtà è più facile di chiunque lo suoni … specialmente se si usa la syntax di base $.ajax({}) contro una delle funzioni di supporto.

Basta inserire la key: value coppia di key: value come si farebbe su qualsiasi object, quando si imposta la richiesta ajax … (perché $(this) non ha ancora cambiato il contesto, è ancora il trigger per la chiamata di bind sopra)

  

Uno dei motivi per cui è meglio che impostare var, è che var è globale e come tale, sovrascrivibile … se hai 2 cose che possono triggersre chiamate ajax, potresti in teoria triggersrle più velocemente di quanto risponde una chiamata ajax, e avresti il ​​valore per la seconda chiamata passata nella prima. Usando questo metodo, sopra, ciò non accadrebbe (ed è anche piuttosto semplice da usare).

Nel mondo di oggi c’è un’altra risposta che è più pulita e presa da un’altra risposta di Overflow dello stack:

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

Ecco la domanda e la risposta originali: jQuery COME ?? passare parametri aggiuntivi al callback di successo per $ .ajax call?

Puoi anche provare qualcosa di simile al seguente:

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

Puoi usare una chiusura di JavaScript:

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

e quando puoi fare:

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

Ho commesso un errore nell’ultimo mio post. Questo è un esempio funzionante per come passare argomenti aggiuntivi nella funzione di callback:

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

Andiamo semplice! 🙂

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

Una soluzione più generale per l’invio di richieste asincrone utilizzando l’API jQuery e le chiusure .ajax() per passare parametri aggiuntivi alla funzione di callback:

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

Per me e altri neofiti che hanno appena contattato Javascript
Penso che la Closeure Solution sia un po ‘troppo confusa.

Mentre l’ho trovato, puoi tranquillamente passare quanti parametri vuoi a ogni callback di ajax usando jquery.

Ecco due soluzioni più semplici .

Il primo, che @zeroasterisk ha menzionato sopra, esempio:

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

Secondo, passare i dati auto-definiti aggiungendoli XHR object che esiste nell’intera durata della vita di richiesta-risposta ajax.

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

Come puoi vedere, queste due soluzioni hanno un inconveniente: devi scrivere un po ‘più di codice ogni volta che scrivere:

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

Maggiori informazioni su $ .ajax: http://api.jquery.com/jquery.ajax/

Se qualcuno viene ancora qui, questa è la mia opinione:

 $('.selector').click(myCallbackFunction.bind({var1: 'hello', var2: 'world'})); function myCallbackFunction(event) { var passedArg1 = this.var1, passedArg2 = this.var2 } 

Cosa succede qui, dopo l’associazione alla funzione di callback, sarà disponibile all’interno della funzione come this .

Questa idea deriva da come React utilizza la funzionalità di bind .

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

Via secondaria:

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

in realtà, il tuo codice non funziona perché quando scrivi:

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

si posiziona una chiamata di funzione come terzo parametro anziché come riferimento di funzione .

Come addendum alla risposta di b01 , il secondo argomento di $.proxy viene spesso utilizzato per conservare this riferimento. Argomenti aggiuntivi passati a $.proxy sono parzialmente applicati alla funzione, pre-compilando i dati. Nota che tutti gli argomenti $.post passati al callback verranno applicati alla fine, quindi doSomething dovrebbe avere quelli alla fine del suo elenco di argomenti:

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

Questo approccio consente inoltre di associare più argomenti alla richiamata:

 function clicked() { var myDiv = $("#my-div"); var mySpan = $("#my-span"); var isActive = true; var callback = $.proxy(doSomething, this, myDiv, mySpan, isActive); $.post("someurl.php",someData,callback,"json"); } function doSomething(curDiv, curSpan, curIsActive, curData) { //"this" still refers to the same "this" as clicked() var serverResponse = curData; }