2009-06-02 60 views
239

有沒有辦法將更多數據傳遞到jQuery中的回調函數?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調用返回的結果。

+13

值得一提的是,從1.4版本開始,jQuery.ajax()已經有了一個上下文設置(http://jquery14.com/day-01/jquery-14)在這裏可以看到它的用法示例:http:// stackoverflow 。com/questions/5097191/ajax-context-option/5097214#5097214 – russau 2011-10-05 08:34:17

+0

我解決了我的問題,在AJAX完成後返回數據,然後執行某些操作。 – Onaiggac 2017-05-25 18:05:13

回答

323

的解決方案是變量綁定到結束。


作爲更基本的例子,這裏是接收並調用的回調函數,以及示例回調函數的示例功能:

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函數的範圍內。

當在doSomething的返回匿名內部函數中引用extraStuff時,它被封閉到外部函數的參數extraStuff。即使在doSomething已返回後也是如此。

我還沒有測試過上述內容,但是我在過去的24小時內編寫了非常類似的代碼,它的工作原理與我所描述的一樣。

根據您的個人偏好/編碼標準,您當然可以傳遞多個變量而不是單個'extraStuff'對象。

0

實際上,你的代碼是不工作,因爲當你寫:

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

您放置函數調用作爲第三個參數,而不是一個函數引用

7

您也可以嘗試像下面這樣:

function clicked() { 

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

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

function doSomething(curData, curDiv) { 

} 
79

使用doSomething(data, myDiv),你實際上調用的函數,不要使對它的引用。

您可以直接傳遞doStomething函數,但必須確保它具有正確的簽名。

如果您想保持原樣,可以使用匿名函數包裝其呼叫。

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

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

在匿名函數代碼中,您可以使用封閉範圍中定義的變量。這是Javascript範圍工作的方式。

+7

爲了清晰起見,這是IMO的最佳解決方案。 `doSomething`函數中沒有額外的`return function(...){...}`函數。我在這裏發現了另一個相同概念的明顯例子:http://theelitist.net/passing-additional-arguments-to-a-callback-function-in-javascript – 2011-10-31 08:28:48

+4

我認爲這是一個問題。如果您的額外數據(本例中爲myDiv)在回調觸發前發生更改,您將獲得新值而不是舊值!在我的情況下,我發射了一個數組中的項目的ajax調用,並且在執行第一次success()調用時,它認爲它在第一個項目中成功了最後一個項目!布拉德豪斯的答案爲我工作。 – Chris 2014-12-09 01:32:16

+0

@Chris是的,捕獲的變量可以在Javascript中更改。如果你不想要這種行爲,你需要創建一個明確的函數來捕獲這個值。最常見的成語是一個自動執行函數`(function(myDiv){...})(myDiv)`來捕獲變量`myDiv`。這隱含在@bradhouse答案中完成。 – 2014-12-09 10:23:36

5

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

我在上一篇文章中犯了一個錯誤。這是工作例如,對於如何通過在回調函數的附加參數:

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

在當今世界上是有另一種答案是清潔的,並從另一個堆棧溢出的答案採取:

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?

0

作爲附錄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; 
} 
47

它比每個人都聽起來更容易...尤其是如果您使用$.ajax({})基本語法與幫手功能之一。

只是通過在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調用響應,並且您將第二次調用的值傳遞給第一個調用。在上面使用這種方法,這不會發生(並且它也很簡單)。

3

讓我們開始吧! :)

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

發送使用jQuery的.ajax() 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); 
    }); 
}; 
1

對於我等新手,誰剛剛接觸用Javascript,
我認爲Closeure Solution是有點太混亂。

雖然我發現,你可以easilly通過儘可能多的參數,你想每個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的請求 - 通過自定義-DATAS響應壽命。

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/

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

如果有人仍然來到這裏,這是我的看法:

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

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

這裏會發生什麼情況,結合回調函數後,它將功能this內面世。

這個想法來自React如何使用bind功能。