в jQuery передать несколько параметров в callback



есть ли способ передать больше данных в функцию обратного вызова в jQuery?



у меня есть две функции, и я хочу, чтобы отзвониться $.post, например, чтобы передать как результирующие данные вызова AJAX, так и несколько пользовательских аргументов



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

}


Я хочу иметь возможность передавать свои собственные параметры в обратный вызов, а также результат, возвращаемый из вызова AJAX.

621   14  

14 ответов:

решение-это связывание переменных через замыкание.


в качестве более простого примера, вот пример функции, которая получает и вызывает функцию обратного вызова, а также пример функции обратного вызова:

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

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

это вызывает обратный вызов и предоставляет один аргумент. Теперь вы хотите предоставить дополнительный аргумент, поэтому вы обернете обратный вызов в закрытие.

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

или, проще говоря, с помощью стрелка ES6 Функции:

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

что касается вашего конкретного примера, я не использовал тег .post функция в jQuery, но быстрое сканирование документации предполагает, что обратный вызов должен быть указатель на функцию со следующей подписью:

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

поэтому я думаю, что решение заключается в следующем:

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

что происходит?

в последней строке doSomething(extraStuff) и вызывается и результат этого вызов - это указатель на функцию.

, потому что extraStuff передается в качестве аргумента doSomething он находится в пределах.

, когда extraStuff ссылается в возвращенной анонимной внутренней функции doSomething он связан замыканием с внешней функцией

при использовании doSomething(data, myDiv), вы фактически вызываете функцию и не делаете ссылку на нее.

вы можете либо передать

это на самом деле проще, чем все это звучит... особенно если вы используете $.ajax({}) базовый синтаксис против одной из вспомогательных функций.

просто пройдите в key: value пара, как вы бы на любом объекте, когда вы устанавливаете свой запрос ajax... (поскольку $(this) еще не изменил контекст, это все еще триггер для вызова привязки выше)

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

одна из причин, по которой это лучше, чем установка var, заключается в том, что var является глобальным и как таковой, перезаписывается... если у вас есть 2 вещи, которые могут вызвать вызовы ajax, вы можете теоретически вызвать их быстрее, чем отвечает вызов ajax, и у вас будет значение для второго вызова, переданного в первый. Используя этот метод, выше, этого не произойдет (и он довольно прост в использовании).

в современном мире есть еще один ответ, который чище, и взят из другого ответа переполнения стека:

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

вот исходный вопрос и ответ: jQuery как?? передайте дополнительные параметры для успешного обратного вызова за $.AJAX-вызов?

вы также можете попробовать что-то вроде следующего:

function clicked() {

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

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

function doSomething(curData, curDiv) {

}

вы можете использовать закрытие JavaScript:

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

и когда вы можете сделать:

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

Я сделал ошибку в последнем моем посте. Это рабочий пример того, как передать дополнительный аргумент в функции обратного вызова:

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

давайте просто ! :)

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

более общее решение для отправки асинхронных запросов с помощью .ajax() jQuery API и закрытие для передачи дополнительных параметров в функцию обратного вызова:

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

для меня и других новичков, которые только что связались с Javascript,
Я думаю, что Closeure Solution - это немного слишком запутанным.

в то время как я обнаружил, что вы можете легко передать столько параметров, сколько хотите для каждого обратного вызова ajax с помощью jquery.

здесь два более простых решения.

первая,@zeroasterisk уже упоминалось выше, пример:

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

второе одно, проходит само-определенные-данные мимо добавление их в XHR object который существует во всем жизненном периоде 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 );
            ...
        } 
    });
});

как вы можете видеть эти два решения имеет недостаток, что : вам нужно написать немного больше кода каждый раз, чем просто написать:

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

подробнее о $.Аякс : http://api.jquery.com/jquery.ajax/

Если кто-то еще приходит сюда, это мое мнение:

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

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

что происходит здесь, после привязки к функции обратного вызова, он будет доступен внутри функции как this.

эта идея исходит из того, как React использует 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);
}

вторичная образом :

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

на самом деле, ваш код не работает, потому что когда вы пишете:

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

вы вызов функции в качестве третьего параметра, а не ссылка на функцию.

в качестве дополнения к B01 не так, второй аргумент $.proxy часто используется для сохранения this ссылка. Дополнительные аргументы передаются в $.proxy частично применяются к функции, предварительно заполняя ее данными. Обратите внимание, что любые аргументы $.post переходы к обратному вызову будут применены в конце, так что doSomething уже в конце списка аргументов:

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

этот подход также позволяет привязать несколько аргументов к обратный вызов:

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

Comments

    Ничего не найдено.