是否有一种方法可以在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调用返回的结果。


当前回答

实际上,这比大家说的要简单得多……特别是当你使用$.ajax({})基本语法和一个helper函数时。

只要传入key: value对,就像你对任何对象一样,当你设置你的ajax请求…(因为$(this)还没有改变上下文,它仍然是上面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>

这比设置var更好的一个原因是,var是全局的,因此,是可重写的…如果有两个东西可以触发ajax调用,理论上可以比ajax调用响应更快地触发它们,并且可以将第二个调用的值传递给第一个调用。使用上面的这个方法,就不会发生这种情况(而且使用起来也很简单)。

其他回答

当使用doSomething(data, myDiv)时,实际上是调用函数,而不是对它进行引用。

您可以直接传递doStomething函数,但必须确保它具有正确的签名。

如果你想让doSomething保持原样,你可以把它的调用包装在一个匿名函数中。

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

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

在匿名函数代码中,可以使用封闭作用域中定义的变量。这就是Javascript作用域的工作方式。

你也可以尝试以下方法:

function clicked() {

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

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

function doSomething(curData, curDiv) {

}

解决方案是通过闭包绑定变量。


作为一个更基本的例子,这里有一个接收和调用回调函数的例子函数,以及一个回调函数的例子:

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"

至于你的具体例子,我没有在jQuery中使用过.post函数,但快速扫描文档建议回调应该是一个具有以下签名的函数指针:

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(extrastutff),调用的结果是一个函数指针。

因为extraStuff是作为参数传递给doSomething的,所以它在doSomething函数的范围内。

当在返回的匿名内部函数doSomething中引用extraStuff时,它通过闭包绑定到外部函数的extraStuff参数。即使在doSomething返回之后也是如此。

我还没有对上面的代码进行测试,但我在过去24小时内编写了非常类似的代码,它的工作原理正如我所描述的那样。

当然,你可以传递多个变量,而不是一个“extraStuff”对象,这取决于你的个人偏好/编码标准。

你可以使用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");
$(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 --
}