jQuery如何在$.ajax调用中传递额外参数给成功回调函数?

19

我在尝试将额外的参数传递给我为成功的ajax调用创建的success回调方法,但似乎徒劳无功。背景是这样的:我有一个页面,其中有许多动态创建的文本框/选择框对,每个对都有一个动态分配的唯一名称,例如name="unique-pair-1_txt-url"和name="unique-pair-1_selectBox",然后第二对具有相同的前缀。

为了重复使用代码,我编写了回调函数来处理数据和选择框的引用。但是,当回调函数被触发时,对选择框的引用返回为'undefined'。我在这里读到此处可以实现。我甚至尝试利用“context”选项,但仍然没有结果。下面是我正在尝试使用的脚本块:

<script type="text/javascript" language="javascript">
$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {
    $j.ajax({
        type: "GET",
        url: $j(urlValue).val(),
        dataType: "jsonp",
        context: selectBox,
        success:function(data){
         loadImagesInSelect(data)
        } ,
        error:function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }

    });
}

function loadImagesInSelect(data) {
var select = $j(this);
select.empty();
$j(data).each(function() {
    var theValue = $j(this)[0]["@value"];
    var theId = $j(this)[0]["@name"];
    select.append("<option value='" + theId + "'>" + theValue + "</option>");
});
select.children(":first").attr("selected", true);

}    
</script>

根据我所了解的,我觉得我离答案很近,但就是找不到关键点。请以你们惯有的忍者隐秘方式帮助我。TIA

****更新**** Nick是一个真正的忍者。他们应该为此发明一个新徽章!他下面的答案解决了我的问题。虽然他提到它只适用于1.4版本,但我可以接受。这是我的最终代码,适用于所有正在接受训练的忍者(和我未来的参考):

<script type="text/javascript" language="javascript">
$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {
    $j.ajax({
        type: "GET",
        url: urlValue+ '?callback=?',
        dataType: "jsonp",
        context: selectBox,
        success: jQuery.proxy(function (data) {
            var select = $j(this);
            select.empty();
            $j(data).each(function() {
                var theValue = $j(this)[0]["@value"];
                var theId = $j(this)[0]["@name"];
                select.append("<option value='" + theId + "'>" + theValue + "</option>");
            });
            select.children(":first").attr("selected", true);
        }, selectBox),
        error:function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }
    });
}
</script>

代码相关的内容翻译如下:看起来正确,控制台有报错吗? 你能否粘贴一下调用 getImages(urlValue, selectBox) 的代码段? - Anurag
仅在回调函数中,selectBox未定义。调用该方法的方式如下: getImages($j('[name=txt_registry_url]').val(),$j('[name=.selImageList]')) - dotnetgeek
也许这太明显了,但是这个选择器 $j('[name=.selImageList]')) 有效吗?根据代码,在 ajax 调用期间如果没有任何更改,selectBox 应该按预期工作。尝试在不同的点记录 selectBox 并检查问题是否在成功回调函数、loadImagesInSelect 函数或甚至是 getImages 函数中未定义。 - Anurag
抱歉,手指有点粗。应该是这样的:getImages($j('[name=txt_registry_url]').val(),$j('[name=selImageList]'))。但正如我所提到的,getImages方法传递了正确的引用,我可以在调试器中检查默认值以进行验证。引用一直存在,直到回调,然后变成未定义。 - dotnetgeek
请查看此答案:https://dev59.com/13NA5IYBdhLWcg3wfd8m#18570951 - Lorenzo Polidori
5个回答

24

这就是我所做的,而且它也很好地起作用了:

$.ajax('URL', {
    myCustomControl: selectBox,
    myCustomVariable: 'teste',
    data:
    {
       myData: 1
    },
    success: function (data, textStats, jqXHR) {
        myFunction(data, textStats, jqXHR, this.myCustomControl, this.myCustomVariable);
    }   
});

您可以将控件和变量添加到ajax调用的参数中。


2
在Chrome中测试,使用jquery-1.11.2。似乎你并不真正需要这个对象:function ajaxParameterTest(p1, p2) { $.ajax({ url: "/Download.aspx?status=true", success: function(data, status, jqXHR){ callbackFunction(data, status, jqXHR, p1, p2); }, dataType: "html", statusCode:{ 404: function(){ alert("你现在无法从服务器检索数据.."); } } }); } - Henrik

14
将这个放到你的 $.ajax 参数中。
invokedata: {
    data1: "yourdata",
    data2: "moredata"
}

在成功函数中使用它的方式如下:

this.invokedata.data1;
this.invokedata.data2;

你的$.ajax调用和success函数也必须是同一个对象的一部分。将你的函数放入一个对象中,并像这样定义它们

function myObject {
    var getImage = function(..) { }
    var loadImagesInSelect = function(..) { }
}

你能告诉我你所说的"$ .ajax"调用和成功函数必须是同一个对象的一部分是什么意思吗?另外,我在jQuery网站上没有看到"invokeData"作为参数。你能详细说明一下这些值吗?它们需要是字符串还是可以是对象引用? - dotnetgeek
我已经更新了我的答案。invokedata被存储在你的对象中,而不是jQuery中。数据可以是任何东西。 - Egor Pavlikhin
我无法让它正常工作,但是@Nick的最终答案似乎有效。谢谢你的帮助。尽管如此,你的解决方案给了我几个更好的想法来清理一下。 - dotnetgeek
1
请查看这个回答,它对我很有用 https://dev59.com/AnE85IYBdhLWcg3w64MA#2542323。我也在尝试做同样的事情。 - Egor Pavlikhin

13

更新: 如果你正在使用 jQuery 1.4,请使用以下代码来简化操作:

success: jQuery.proxy(function (data) {
    var select = $j(this);
    select.empty();
    $j(data).each(function() {
        var theValue = $j(this)[0]["@value"];
        var theId = $j(this)[0]["@name"];
        select.append("<option value='" + theId + "'>" + theValue + "</option>");
    });
    select.children(":first").attr("selected", true);
}, selectBox)

Nick,这似乎不起作用。我首先尝试使用匿名方法,但仍然没有任何反应。我可以看到该方法被调用,但无法进入匿名方法。因此,我将其更改为使用外部方法,以便我可以在其上中断。然后它返回未定义。 - dotnetgeek
@dotnetgeek - 你是如何调用外部方法的?它应该只是像这样具有签名的 success: externalMethodNamefunction externalMethodName(data) - Nick Craver
@dotnetgeek - 这就是我试图传达的部分,你无法控制传递给该函数的参数,格式始终为 function(data, textStatus, XMLHttpRequest),但是你可以通过设置 context: something 来确定该函数内部所指代的 this,当函数运行时,something 将成为 this - Nick Craver
@dotnetgeek - 希望你正在使用jQuery 1.4,我更新了答案并提供了一种更可靠的方法来解决它,看看是否会有任何问题。 - Nick Craver
@Nick,你太棒了!这个例子完美地运行了。我认为之前的也可以工作。除了你的建议外,关键的改变是更改了我传递给JSONP服务的参数。我最初写的是:"http://<url>:<port>?callback=loadImagesInSelect",我把它改成了"http://<url>:<port>?callback=?"。非常感谢你的坚持和耐心!我会更新我的问题并附上完整的正确代码。 - dotnetgeek
显示剩余4条评论

4

this 超出范围

只是让你(或其他人)明白1,在你的原始示例中,在 loadImagesInSelect()this 未定义的原因是因为该函数处于不同的作用域,作用域不会像那样“级联”2

当您在 AJAX 调用中指定了 selectBox 的 "context" 后,它设置了 "success" 和 "error" 函数的上下文 (this)。 (恰好它们都是匿名函数。)此时,this 在这两个函数中均被定义为 selectBox 的值。现在,在传递给 "success" 的函数中,您调用 loadImagesInSelect()。当您调用一个函数时,它会创建一个新的作用域。在这个作用域中,this 将在严格模式下为 undefined,在非严格模式下将为 window


以图表形式呈现(在严格模式下3):

// this = window (global scope)

$j = jQuery.noConflict();
function getImages(urlValue, selectBox) {

    // this = undefined (function scope level 1)

    $j.ajax({
        type: "GET",
        url: $j(urlValue).val(),
        dataType: "jsonp",
        context: selectBox,
        success: function(data) {

            // this = selectBox (function scope level 2)

            loadImagesInSelect(data);
        },
        error: function(xhr, ajaxOptions, thrownError) {

            // this = selectBox (function scope level 2)

            alert(xhr.status);
            alert(thrownError);
        }
    });
}

function loadImagesInSelect(data) {

    // this = undefined (function scope level 3)

    var select = $j(this);
    select.empty();
    $j(data).each(function() {
        var theValue = $j(this)[0]["@value"];
        var theId = $j(this)[0]["@name"];
        select.append("<option value='" + theId + "'>" + theValue + "</option>");
    });
    select.children(":first").attr("selected", true);
}

$.proxy()是多余的

在你更新的代码中,使用$.proxy()是多余的。你使用$.proxy()来将this传递到先前被称为loadImagesInSelect()的函数中,但是你把这个函数移到了“success”中(而不是从“success”中调用它)。它现在已经可以访问由“context”指定的this值。

你可以在更新的代码中删除对“success”函数的$.proxy()包装,它仍然可以正常工作。

我知道你提问已经几年了,但我希望这能有所帮助。

  1. 我希望这不会显得轻蔑;这并不是我的本意。
  2. 至少,在你调用函数时,并且没有上下文时是这样的。如果你在一个函数内定义了一个函数(即闭包),那么外部函数中的任何变量都可以在内部函数中使用。然而,外部函数的上下文(this变量)仍然无法在内部函数中使用。
  3. 对于非严格模式,请将undefined替换为window
  4. 或者在ECMAScript 5中使用本地的Function.prototype.bind()

1
您可以使用indexValue属性进行传递:
var someData = "hello";

jQuery.ajax({
    url: "http://maps.google.com/maps/api/js?v=3",
    indexValue: {param1:someData, param2:"Other data 2", param3: "Other data 3"},
    dataType: "script"
}).done(function() {
    console.log(this.indexValue.param1);
    console.log(this.indexValue.param2);
    console.log(this.indexValue.param3);
}); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接