首页 文章

jQuery将更多参数传递给回调

提问于
浏览
247

有没有办法将更多数据传递给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调用返回的结果 .

14 回答

  • 19

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


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

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

    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(extraStuff) ,并且该调用的结果是函数指针 .

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

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

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

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

  • 0

    使用 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作用域的工作方式 .

  • 5

    它's actually easier than everyone' s使它听起来......特别是如果你使用 $.ajax({}) 基本语法与其中一个辅助函数 .

    只需传入 key: value 对就像在任何对象上一样,当您设置ajax请求时...(因为 $(this) 还没有't changed context yet, it'仍然是上面绑定调用的触发器)

    <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调用响应更快地触发它们,你有第二个调用传递给第一个调用的值 . 使用上面的方法,这不会发生(并且使用它也很简单) .

  • 7

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

    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 HOW TO?? pass additional parameters to success callback for $.ajax call?

  • 1

    您还可以尝试以下内容:

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

    您可以使用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");
    
  • 50

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

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

    我们走吧! :)

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

    使用.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);
         });
    };
    
  • 3

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

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

    这是 two easier solutions .

    第一个,上面提到了 @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 );
                ...
            } 
        });
    });
    

    第二个,通过将自定义数据添加到整个ajax-request-response生命周期中存在的 XHR object 中来传递自定义数据 .

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

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

  • 1

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

    $('.selector').click(myCallbackFunction.bind({var1: 'hello', var2: 'world'}));
    
    function myCallbackFunction(event) {
        var passedArg1 = this.var1,
            passedArg2 = this.var2
    }
    

    这里发生了什么,绑定到回调函数后,它将在其中可用功能为 this .

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

  • 1
    $(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 --
    }
    
  • 332

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

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

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

  • 2

    作为b01's answer的附录, $.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;
    }
    

相关问题