有没有办法将更多数据传递给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调用返回的结果。
答案 0 :(得分:335)
解决方案是通过闭包来绑定变量。
作为一个更基本的例子,这里是一个接收和调用回调函数的示例函数,以及一个示例回调函数:
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'对象。
答案 1 :(得分:79)
使用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范围的工作方式。
答案 2 :(得分:50)
它实际上比每个人都更容易听起来更容易......特别是如果你使用$.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是全局的,因此是可覆盖的...如果你有两件事可以触发ajax调用,理论上你可以比ajax调用更快地触发它们响应,你有第二个调用传递给第一个的值。使用上面的方法,这种情况不会发生(而且使用它也很简单)。
答案 3 :(得分:20)
在今天的世界中,还有一个更清晰的答案,并取自另一个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?
答案 4 :(得分:7)
您还可以尝试以下内容:
function clicked() {
var myDiv = $("#my-div");
$.post("someurl.php",someData,function(data){
doSomething(data, myDiv);
},"json");
}
function doSomething(curData, curDiv) {
}
答案 5 :(得分: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");
答案 6 :(得分: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;
}
答案 7 :(得分:3)
让我们变得简单! :)
$.ajax({
url: myUrl,
context: $this, // $this == Current $element
success: function(data) {
$.proxy(publicMethods.update, this)(data); // this == Current $element
}
});
答案 8 :(得分:2)
使用.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);
});
};
答案 9 :(得分:1)
对于我和其他刚接触过Javascript的新手,
我认为Closeure Solution
有点太混乱了。
虽然我发现了这一点,但您可以使用jquery轻松地将所有参数传递给每个ajax回调。
以下是两个更简单的解决方案。
第一个, @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);
详细了解$ .ajax:http://api.jquery.com/jquery.ajax/
答案 10 :(得分: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 --
}
答案 11 :(得分:1)
如果有人还来这里,这是我的看法:
$('.selector').click(myCallbackFunction.bind({var1: 'hello', var2: 'world'}));
function myCallbackFunction(event) {
var passedArg1 = this.var1,
passedArg2 = this.var2
}
这里发生的事情,在绑定到回调函数后,它将在函数this
中可用。
这个想法来自React如何使用bind
功能。
答案 12 :(得分:0)
$.post("someurl.php",someData,doSomething(data, myDiv),"json");
您将函数调用作为第三个参数而不是函数引用。
答案 13 :(得分: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;
}