jQuery przekazuje więcej parametrów do funkcji callback

Czy jest sposób na przekazanie większej ilości danych do funkcji zwrotnej w jQuery?

Mam dwie funkcje i chcę, aby wywołanie zwrotne do $.post, na przykład, przekazać zarówno dane wynikowe wywołania AJAX, jak i kilka niestandardowych argumentów

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

}

Chcę być w stanie przekazać własne parametry do wywołania zwrotnego, jak również wynik zwracany z połączenia AJAX.

Author: TylerH, 2009-06-02

14 answers

Rozwiązaniem jest powiązanie zmiennych poprzez zamknięcie.


Jako bardziej podstawowy przykład, oto przykładowa funkcja, która odbiera i wywołuje funkcję zwrotną, a także przykładowa funkcja zwrotna:

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

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

To wywołuje callback i dostarcza jeden argument. Teraz chcesz podać dodatkowy argument, więc zawiń callback w zamknięciu.

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

Lub prościej używając funkcji strzałek ES6 :

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

Co do twojego konkretny przykład, nie używałem funkcji .post w jQuery, ale Szybkie skanowanie dokumentacji sugeruje, że wywołanie powinno być wskaźnikiem funkcji z następującym podpisem:

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

Dlatego myślę, że rozwiązanie jest następujące:

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");
};
Co się dzieje?

W ostatnim wierszu doSomething(extraStuff) jest wywołane , a wynikiem tego wywołania jest wskaźnik funkcji .

Ponieważ extraStuff jest przekazywana jako argument do doSomething jest w ramach funkcji doSomething.

Gdy {[7] } jest odwołana w zwracanej anonimowej funkcji wewnętrznej doSomething, jest ona związana zamknięciem do zewnętrznego argumentu funkcji extraStuff. Jest to prawdą nawet po powrocie doSomething.

Nie testowałem powyższego, ale napisałem bardzo podobny kod w ciągu ostatnich 24 godzin i działa tak, jak opisałem.

Możesz oczywiście przekazać wiele zmiennych zamiast jednego obiektu "extraStuff" w zależności od Twojego osobistego preferencje / standardy kodowania.

 331
Author: bradhouse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-09 22:27:13

Podczas używania doSomething(data, myDiv), wywołujesz funkcję i nie odwołujesz się do niej.

Możesz przekazać funkcję doStomething bezpośrednio, ale musisz upewnić się, że ma prawidłowy podpis.

Jeśli chcesz zachować doSomething tak jak jest, możesz zawinąć jego wywołanie w funkcję anonimową.

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

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

Wewnątrz kodu funkcji anonimowej można użyć zmiennych zdefiniowanych w obszarze załączającym. Tak działa JavaScript scoping.

 79
Author: Vincent Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 13:28:56

To łatwiejsze niż wszyscy mówią... zwłaszcza jeśli używasz składni bazowej $.ajax({}) vs. jednej z funkcji pomocniczych.

Po prostu podaj parę key: value, tak jak na dowolnym obiekcie, podczas konfigurowania żądania ajax... (ponieważ $(this) nie zmienił jeszcze kontekstu, nadal jest wyzwalaczem powyższego wywołania bind)

<script type="text/javascript">
$(".qty input").bind("keypress change", function() {
    $.ajax({
        url: "/order_items/change/"+$(this).attr("data-order-item-id")+"/qty:"+$(this).val()+"/returnas.json",
        type: "POST",
        dataType: "json",
        qty_input: $(this),
        anything_else_i_want_to_pass_in: "foo",
        success: function(json_data, textStatus, jqXHR) {
            /* here is the input, which triggered this AJAX request */
            console.log(this.qty_input);
            /* here is any other parameter you set when initializing the ajax method */
            console.log(this.anything_else_i_want_to_pass_in);
        }
    });
});
</script>

Jednym z powodów, dla których jest to lepsze niż ustawienie var, jest to, że var jest globalny i jako taki, nadpisywalny... jeśli masz 2 rzeczy które mogą wyzwalać połączenia ajax, teoretycznie można wyzwalać je szybciej niż połączenia ajax odpowiada, a wartość dla drugiego połączenia przekazywana jest do pierwszego. Korzystanie z tej metody, powyżej, że nie stanie się (i to jest dość proste w użyciu zbyt).

 49
Author: zeroasterisk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-08 20:36:53

W dzisiejszym świecie istnieje inna odpowiedź, która jest czystsza, a wzięta z innej odpowiedzi przepełnienia stosu:

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

Oto oryginalne pytanie i odpowiedź: jQuery jak?? przekaż dodatkowe parametry do wywołania zwrotnego sukcesu za $.połączenie z Ajaxem?

 19
Author: b01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:09

Możesz również spróbować czegoś takiego:

function clicked() {

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

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

function doSomething(curData, curDiv) {

}
 7
Author: Rohan Almeida,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-02 12:04:04

Możesz użyć zamknięcia JavaScript:

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

I kiedy możesz zrobić:

$.post("someurl.php",data,wrapper(var1, var2, etc...),"html");
 5
Author: Artem Barger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-02 12:13:15

Popełniłem błąd w ostatnim poście. To jest przykład pracy, jak przekazać dodatkowy argument w funkcji 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;
}
 3
Author: Igor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-03 15:25:59

Let ' s go simple ! :)

$.ajax({
    url: myUrl,
    context: $this, // $this == Current $element
    success: function(data) {
        $.proxy(publicMethods.update, this)(data); // this == Current $element
    }
});
 3
Author: molokoloco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 11:31:37

Bardziej ogólne rozwiązanie do wysyłania asynchronicznych żądań za pomocą .ajax() jQuery API i zamknięcia, aby przekazać dodatkowe parametry do funkcji 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);
     });
};
 2
Author: Lorenzo Polidori,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-02 10:36:07

Dla mnie i innych początkujących, którzy właśnie skontaktowali się z Javascript,
Myślę, że Closeure Solution jest trochę zbyt mylące.

Podczas gdy znalazłem, że, można łatwo przekazać tyle parametrów, ile chcesz do każdego wywołania zwrotnego ajax za pomocą jquery.

Oto dwa łatwiejsze rozwiązania.

Pierwszy, który @ zeroasterisk wspomniał powyżej, przykład:

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

Drugi, podaj zdefiniowane przez siebie dane, dodając je do XHR object która istnieje w cały czas życia ajax-request-response.

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

Jak widać te dwa rozwiązania mają wadę: za każdym razem trzeba napisać trochę więcej kodu niż tylko napisać:

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

Czytaj więcej o $.ajax: http://api.jquery.com/jquery.ajax/

 1
Author: lyfing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-22 04:14:22

Jeśli ktoś jeszcze tu przyjdzie, to jest to moje zdanie:

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

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

Co się tutaj dzieje, po powiązaniu z funkcją callback, będzie ona dostępna w ramach funkcji jako this.

Ten pomysł pochodzi z tego, jak React używa funkcjonalności bind.

 1
Author: Kőhalmy Zoltán,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-15 08:46:20
$(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);
}

Droga Drugorzędna:

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 --
}
 1
Author: Musa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-01 10:07:51

Właściwie Twój kod nie działa, ponieważ kiedy piszesz:

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

Jako trzeci parametr umieszczasz wywołanie funkcji, a nie odwołanie do funkcji.

 0
Author: jrharshath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-02 11:53:15

Jako dodatek do odpowiedzi B01 , drugi argument $.proxy jest często używany do zachowania odniesienia this. Dodatkowe argumenty przekazane do $.proxy są częściowo stosowane do funkcji, wstępnie wypełniając ją danymi. Zauważ, że wszelkie argumenty $.post przekazane do wywołania zwrotnego zostaną zastosowane na końcu, więc doSomething powinny mieć te na końcu listy argumentów:

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

To podejście pozwala również na powiązanie wielu argumentów z wywołaniem zwrotnym:

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;
}
 0
Author: hyperslug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:46