关于javascript:jQuery将更多参数传递给回调

jQuery pass more parameters into callback

有没有办法将更多数据传递给jQuery中的回调函数?

我有两个函数,我希望回调到$.post,例如,传入AJAX调用的结果数据,以及一些自定义参数

1
2
3
4
5
6
7
8
9
10
11
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调用返回的结果。


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

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

1
2
3
4
5
6
7
function callbackReceiver(callback) {
    callback("Hello World");
}

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

这会调用回调并提供单个参数。现在你想提供一个额外的参数,所以你将回调包装在闭包中。

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

或者,更简单地使用ES6箭头功能:

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

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

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

因此我认为解决方案如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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,所以它在doSomething函数的范围内。

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

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

您当然可以传递多个变量而不是单个'extraStuff'对象,具体取决于您的个人偏好/编码标准。


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

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

如果你想按照它的方式保持doSomething,你可以将它的调用包装在一个匿名函数中。

1
2
3
4
5
6
7
8
9
10
function clicked() {
    var myDiv = $("#my-div");
    $.post("someurl.php",someData, function(data){
      doSomething(data, myDiv)
    },"json");
}

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

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


它实际上比每个人都更容易听起来更容易...特别是如果你使用$.ajax({})基本语法与其中一个辅助函数。

只需传入key: value对就像在任何对象上一样,当你设置ajax请求时...(因为$(this)还没有改变上下文,它仍然是上面绑定调用的触发器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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);
        }
    });
});

这比设置var更好的原因之一是var是全局的,因此是可覆盖的...如果你有2个可以触发ajax调用的东西,理论上你可以比ajax调用响应更快地触发它们,你有第二个调用传递给第一个调用的值。使用上面的方法,这不会发生(并且使用它也很简单)。


在今天的世界中,还有另一个更清晰的答案,并取自另一个Stack Overflow答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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调用的成功回调?


您还可以尝试以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
function clicked() {

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

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

function doSomething(curData, curDiv) {

}

您可以使用JavaScript的闭包:

1
2
3
4
5
6
7
function wrapper( var1, var2,....) // put here your variables
{
  return function( data, status)
  {
     //Handle here results of call
  }
};

当你能做到:

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


我们走吧! :)

1
2
3
4
5
6
7
$.ajax({
    url: myUrl,
    context: $this, // $this == Current $element
    success: function(data) {
        $.proxy(publicMethods.update, this)(data); // this == Current $element
    }
});

我在上一篇文章中犯了一个错误。这是如何在回调函数中传递其他参数的工作示例:

1
2
3
4
5
6
7
8
9
10
11
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() jQuery API发送异步请求的更通用的解决方案和闭包将其他参数传递给回调函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
     });
};

如果有人还来这里,这是我的看法:

1
2
3
4
5
6
$('.selector').click(myCallbackFunction.bind({var1: 'hello', var2: 'world'}));

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

这里发生了什么,在绑定到回调函数之后,它将在函数中作为this使用。

这个想法来自React如何使用bind功能。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$(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);
}

次要方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 --
}


对于我和其他刚接触过Javascript的新手,
我认为Closeure Solution有点太混乱了。

虽然我发现了这一点,但您可以使用jquery轻松地将所有参数传递给每个ajax回调。

这是两个更简单的解决方案

@zeroasterisk上面提到的第一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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-request-response生命周期中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 );
            ...
        }
    });
});

正如您所看到的,这两个解决方案的缺点是:您每次都需要编写更多代码而不仅仅是编写代码:

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

阅读更多关于$ .ajax的信息:http://api.jquery.com/jquery.ajax/


作为b01答案的补充,$.proxy的第二个参数通常用于保留this引用。传递给$.proxy的其他参数部分应用于函数,预填充数据。请注意,任何参数$.post传递给回调都将在最后应用,因此doSomething应该在其参数列表的末尾有那些:

1
2
3
4
5
6
7
8
9
10
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;
}

此方法还允许将多个参数绑定到回调:

1
2
3
4
5
6
7
8
9
10
11
12
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;
}

实际上,你的代码不起作用,因为当你写:

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

您将函数调用作为第三个参数而不是函数引用。