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调用返回的结果。

210129 次浏览

实际上,你的代码不能工作,因为当你写:

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

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

你也可以尝试以下方法:

function clicked() {


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


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


function doSomething(curData, curDiv) {


}

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

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

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


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

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函数说明:

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”对象,这取决于你的个人偏好/编码标准。

我在上一篇帖子中犯了一个错误。这是一个如何在回调函数中传递额外参数的工作示例:

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

在当今世界,有另一个更清晰的答案,来自另一个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如何??为$的成功回调传递附加参数。ajax调用吗? < / p >

作为b01的回答的补充,$.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;
}

实际上,这比大家说的要简单得多……特别是当你使用$.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调用响应更快地触发它们,并且可以将第二个调用的值传递给第一个调用。使用上面的这个方法,就不会发生这种情况(而且使用起来也很简单)。

让我们简单点!:)

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

使用.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);
});
};
对于我和其他刚接触Javascript的新手来说,
我认为Closeure Solution有点太混乱了

虽然我发现,你可以很容易地传递尽可能多的参数,因为你想每个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-request-response生命周期中
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/

$(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 --
}

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

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


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

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

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