使用AJAX调用的JavaScript对话框不同步

本文关键字:对话框 同步 JavaScript AJAX 调用 使用 | 更新日期: 2023-09-27 18:20:17

我的某些JavaScript出现问题,该JavaScript旨在显示基于C#ViewModel的JQUERY对话框。

我在中继器中有一个ASP下拉菜单,显示"注册日期"信息。其想法是,当用户从列表中选择日期时,JavaScript对话框将出现,使用特定的视图模型属性显示与该注册相关的更全面的信息摘要。函数CustomerSummary是在有问题页面的标准$(document).ready上调用的。

JS代码

function CustomerSummary() {
    var registrationId;
    var data;
    $("select[id$='ddlRegistration']").change(function () {
        registrationId = $(this).val();
        if (registrationId !== 'default')
        {
            data = MakeAJAXCall(registrationId);
            $("#dialog").html("Registration Id: " + data.RegistrationId + "<br />" +
                               "Permit From: " + data.PermitFrom + "<br />" +
                               "Permit To: " + data.PermitTo + "<br />" +
                               "Registration Status: " + data.RegistrationStatus 
            );
            $("#dialog").dialog({
                show: {
                    effect: "blind",
                    duration: 1000
                },
                hide: {
                    effect: "explode",
                    duration: 1000
                }
            });
        }
    });
    function MakeAJAXCall(regId)
    {
        $.ajax({
            type: "post",
            contentType: "application/json; charset=utf-8",
            dataType: "text json",
            url: "/Secure/CustomerSummary.aspx/GetRegistration",
            data: "{ regId: '"" + regId + "'" }",
            success: function (msg) {                
                data = msg.d;                
            },
            error: function (xOptions, textStatus)
            {                
                console.log(textStatus);
                console.log(xOptions);
            }
        });
    }    
}

C#代码

[WebMethod(), ScriptMethod(UseHttpGet=false)]
        public static RegistrationViewModel GetRegistration(int regId)
        {            
            RegistrationRepository repo = new RegistrationRepository();
            RegistrationViewModel reg = new RegistrationViewModel();
            RegistrationFactory regFac = new RegistrationFactory();
            reg = regFac.ConvertToRegistrationViewModel(repo.GetRegistration(regId));
            return reg;
        }

调试期间发生了什么

这里发生的事情就在这条线上:

$("#dialog").html("Registration Id: " + data.RegistrationId + "<br />" +

我得到错误:

Uncaught TypeError: Cannot read property 'RegistrationId' of undefined 

当我第一次从菜单中选择日期并调用更改功能时,我会收到上面的错误消息,并且没有出现对话框,如果我检查data,我确实可以看到它是未定义的。然后,一旦我从下拉菜单中选择了一个不同的数据,并且我到达了断点(change.(function)数据被设置为从上一次AJAX调用中检索到的数据,对话框就会弹出,但带有以前的请求数据,结果就会停留在这个周期中,每次我选择一个数据时,我都会看到以前的选择信息。

有人能指出为什么我总是有一个选择不同步吗?我相信这是由于第一个更改请求,但我不明白为什么AJAX调用在我选择下一个下拉项之前没有将data设置为所需的结果。

使用AJAX调用的JavaScript对话框不同步

这将不适用于

data = MakeAJAXCall(registrationId);

因为MakeAJAXCall正在执行Ajax调用,而且它是异步的,所以返回的执行顺序与函数中的返回不同。因此,您需要使用回调。

尝试将您的代码更改为类似以下内容:

MakeAJAXCall(registrationId, function(data){
 $("#dialog").html("Registration Id: " + data.RegistrationId + "<br />" +
                                   "Permit From: " + data.PermitFrom + "<br />" +
                                   "Permit To: " + data.PermitTo + "<br />" +
                                   "Registration Status: " + data.RegistrationStatus 
                );
});

然后在Ajax呼叫中,您也需要进行以下更改:

function MakeAJAXCall(regId, callback)
    {
        $.ajax({
            type: "post",
            contentType: "application/json; charset=utf-8",
            dataType: "text json",
            url: "/Secure/CustomerSummary.aspx/GetRegistration",
            data: "{ regId: '"" + regId + "'" }",
            success: function (msg) {                
                data = msg.d;  
                callback(data); //<--- You callback function is called here              
            },
            error: function (xOptions, textStatus)
            {                
                console.log(textStatus);
                console.log(xOptions);
            }
        });
    }    
Ajax中的第一个A用于异步。这意味着您的呼叫将在后台运行,这就是您使用回调的原因。当您的调用成功/出错时,比如10秒后,调用正确的函数。与此同时,设置和创建结果的其他代码也会运行,很可能是在从ajax查询收到任何答案之前。正如@Dalorzo所建议的,将结果对话框代码封装在回调中,这样您的代码将在收到结果后运行