jQuery passe plus de paramètres dans le callback

Est-il un moyen de passer plus de données dans une fonction de rappel en jQuery?

j'ai deux fonctions et je veux que le rappel au $.post , par exemple, passer à la fois les données résultantes de L'appel AJAX, ainsi que quelques arguments personnalisés

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

}

je veux être en mesure de passer dans mes propres paramètres à un rappel, ainsi que le résultat retourné de L'appel AJAX.

247
demandé sur TylerH 2009-06-02 15:35:26
la source

14 ответов

la solution est la liaison des variables par la fermeture.


comme exemple plus simple, voici un exemple de fonction qui reçoit et appelle une fonction de rappel, ainsi qu'un exemple de fonction de rappel:

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

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

cela appelle le rappel et fournit un seul argument. Maintenant, vous voulez fournir un argument supplémentaire, donc vous envelopper le rappel dans la fermeture.

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

Ou, plus simplement en utilisant fonctions Flèche ES6 :

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

comme pour votre exemple spécifique, je n'ai pas utilisé la fonction .post dans jQuery, mais un balayage rapide de la documentation suggère que le rappel devrait être un indicateur de fonction avec la signature suivante:

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

donc je pense que la solution est la suivante:

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

que se passe-t-il?

À la dernière ligne, doSomething(extraStuff) est invoquée et le résultat de l'invocation est un pointeur de fonction .

parce que extraStuff est passé comme argument à doSomething il est dans le champ d'application de la fonction doSomething .

quand extraStuff est référencé dans la fonction interne anonyme retournée de doSomething il est lié par fermeture de l'argument extraStuff de la fonction externe. Cela est vrai même après le retour de doSomething .

Je n'ai pas testé ce qui précède, mais j'ai écrit un code très similaire dans les dernières 24 heures et il fonctionne comme je l'ai décrit.

vous pouvez bien sûr passer plusieurs variables au lieu d'un seul objet 'extraStuff' en fonction de vos préférences personnelles/normes de codage.

331
répondu bradhouse 2017-07-10 01:27:13
la source

lorsque vous utilisez doSomething(data, myDiv) , vous appelez effectivement la fonction et ne faites pas référence à elle.

vous pouvez passer la fonction doStomething directement, mais vous devez vous assurer qu'il a la signature correcte.

si vous voulez garder le doSomething comme il est, vous pouvez envelopper son appel dans une fonction anonyme.

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

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

dans le code de fonction anonyme, vous pouvez utiliser les variables définies dans le champ d'application. C'est la façon dont Javascript scoping fonctionne.

79
répondu Vincent Robert 2014-11-24 16:28:56
la source

c'est en fait plus facile que tout le monde le fait sonner... surtout si vous utilisez la syntaxe de base $.ajax({}) par rapport à l'une des fonctions d'aide.

passez simplement dans la paire key: value comme vous le feriez sur n'importe quel objet, lorsque vous configurez votre requête ajax... (parce que $(this) n'a pas encore changé de contexte, c'est toujours le déclencheur de l'appel bind ci-dessus)

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

une des raisons pour lesquelles c'est mieux que le cadre le var, c'est que le var est mondiale et en tant que tel, overwritable... si vous avez 2 choses qui peuvent déclencher des appels ajax, vous pourriez en théorie les déclencher plus rapidement que les réponses d'appel ajax, et vous auriez la valeur pour le deuxième appel passé dans le premier. En utilisant cette méthode, ci-dessus, cela ne se produirait pas (et il est assez simple à utiliser aussi).

49
répondu zeroasterisk 2012-03-09 00:36:53
la source

dans le monde d'aujourd'hui il y a une autre réponse qui est plus propre, et tirée d'une autre réponse de débordement de pile:

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

Voici la question et la réponse originales: jQuery comment faire?? passer des paramètres supplémentaires à succès callback pour$.appel ajax?

19
répondu b01 2017-05-23 14:55:09
la source

vous pouvez aussi essayer quelque chose comme:

function clicked() {

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

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

function doSomething(curData, curDiv) {

}
7
répondu Rohan Almeida 2009-06-02 16:04:04
la source

vous pouvez utiliser une fermeture de JavaScript:

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

et quand vous pouvez le faire:

$.post("someurl.php",data,wrapper(var1, var2, etc...),"html");
5
répondu Artem Barger 2009-06-02 16:13:15
la source

j'ai fait une erreur dans mon dernier post. Ceci est un exemple de travail pour passer l'argument supplémentaire dans la fonction 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
répondu Igor 2010-09-03 19:25:59
la source

soyons simples ! :)

$.ajax({
    url: myUrl,
    context: $this, // $this == Current $element
    success: function(data) {
        $.proxy(publicMethods.update, this)(data); // this == Current $element
    }
});
3
répondu molokoloco 2013-04-09 15:31:37
la source

une solution plus générale pour envoyer des requêtes asynchrones en utilisant l ' .ajax() API jQuery et fermetures pour passer des paramètres supplémentaires à la fonction de rappel:

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
répondu Lorenzo Polidori 2013-09-02 14:36:07
la source

pour moi, et d'autres débutants qui viennent de contacter Javascript,
151970920" Je pense que le Closeure Solution est un peu trop confus.

bien que j'ai trouvé que, vous pouvez facilement passer autant de paramètres que vous voulez à chaque appel ajax en utilisant jquery.

Voici deux solutions plus faciles .

le premier, que @zeroasterisk a mentionné ci-dessus, exemple:

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

Deuxième, et ainsi de passer de l'auto-défini-données en les ajoutant dans le XHR object qui existe dans toute la durée de vie 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 );
            ...
        } 
    });
});

comme vous pouvez le voir ces deux solutions a un inconvénient que: vous avez besoin d'écrire un peu plus de code à chaque fois que juste écrire:

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

plus d'informations à propos de $.ajax: http://api.jquery.com/jquery.ajax /

1
répondu lyfing 2014-05-22 08:14:22
la source

si quelqu'un vient encore ici, c'est ma prise:

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

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

ce qui se passe ici, après liaison à la fonction de rappel, il sera disponible dans la fonction comme this .

cette idée vient de la façon dont React utilise la fonctionnalité bind .

1
répondu Kőhalmy Zoltán 2016-10-15 11:46:20
la source
$(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);
}

Secondaire": 151930920"

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
répondu Musa 2016-11-01 13:07:51
la source

en fait, votre code ne fonctionne pas parce que lorsque vous écrivez:

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

vous placez un appel de fonction comme troisième paramètre plutôt qu'un référence de fonction .

0
répondu jrharshath 2009-06-02 15:53:15
la source

comme addenda à la réponse de b01 , le deuxième argument de $.proxy est souvent utilisé pour conserver la référence this . Les arguments supplémentaires passés à $.proxy sont partiellement appliqués à la fonction, la pré-remplir avec des données. Notez que tout argument $.post passe à la callback sera appliqué à la fin, donc doSomething devrait avoir ceux à la fin de sa liste d'arguments:

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

cette approche également permet à plusieurs arguments d'être liés au callback:

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
répondu hyperslug 2017-05-23 15:02:46
la source