jQuery 将更多参数传递给回调

IT技术 javascript jquery function callback arguments
2021-02-06 20:49:39

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

6个回答

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


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

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 箭头函数

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

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

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”对象。

由于示例的特殊性,对于尝试将其应用于更一般问题的用户来说,这可能有点难以理解。我添加了一个简化的示例使其更容易理解,以及一个箭头函数示例,以防止此问题作为新发布的建议副本的副本而关闭。如果您觉得我的编辑与您回答的初衷背道而驰,或者在任何其他方面不合适,请随时将其回滚。
2021-03-17 20:49:39
Ihor:关于两种声明样式之间的差异,您是完全正确的。一个很好的解释在这里:stackoverflow.com/questions/336859/...
2021-03-24 20:49:39
正在讨论此答案的修订版 4
2021-03-30 20:49:39
这不是真的。不同的范围规则适用于这两个函数声明。行为因 JS 运行时(读取浏览器)而异。还尝试比较 Firebug 中堆栈跟踪/断点中显示的函数名称。
2021-04-09 20:49:39
“var doSomething =”的目的是什么?这与仅将 doSomething 声明为函数(即 function doSomething(...) {} )有何不同
2021-04-11 20:49:39

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

@Chris 是的,可以在 Javascript 中更改捕获的变量。如果您不希望出现这种行为,则需要创建一个显式函数来捕获该值。最常见的习惯用法是一个自执行函数(function(myDiv){ ... })(myDiv)来捕获变量myDiv这是在@bradhouse 答案中隐式完成的。
2021-03-12 20:49:39
如果你调用这个 ajax n 次,这个方法会创建 n 个不同的函数并将它们传递给成功回调。这在性能方面很糟糕。为了避免这个@zeroasterisk 的回答是好的。
2021-03-31 20:49:39
我同意@WilliamDenniss,恕我直言,这是最好的,简单明了的解决方案
2021-03-31 20:49:39
为清楚起见,这是 IMO 的最佳解决方案。return function(...){...}函数内没有额外doSomething函数。我在这里找到了相同概念的另一个明显例子:theelitist.net/...
2021-04-01 20:49:39
我觉得这个有问题。如果您的额外数据(在本例中为 myDiv)在回调触发之前发生更改,您将获得新值而不是旧值!就我而言,我正在对数组中的项目触发 ajax 调用,当第一次成功()调用执行时,它认为它在最后一个项目上成功了,而它是第一个!布拉德豪斯的回答对我有用。
2021-04-01 20:49:39

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

var 是全局的,因此可以覆盖”。如果您在函数中声明它,则不是,这也比上面的解决方案更具可读性。使用闭包是一种更简洁的方法 - 请在此处查看我的答案:stackoverflow.com/a/18570951/885464
2021-03-14 20:49:39
这绝对是绝妙的。我以前怎么从来没见过这个。我不需要closure我只需要它工作,这绝对是王牌、干净、简单和非全球性的。
2021-03-17 20:49:39
听起来像是传递额外参数以回调给我的最佳方式。如果有人看到这种方法的缺点,我会感兴趣吗?最简单,最优雅。谢谢!
2021-03-27 20:49:39
这正是我要找的。我不知道当您将 dataType 指定为 json 时,它会自动为您解析响应。那个好(:
2021-03-31 20:49:39
@LorenzoPolidori 我不同意,我发现附加参数方法更具可读性。
2021-04-02 20:49:39

在当今世界,还有一个更简洁的答案,取自另一个 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?? 将附加参数传递给 $.ajax 调用的成功回调?

您还可以尝试以下操作:

function clicked() {

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

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

function doSomething(curData, curDiv) {

}