0

我有一个 ASP 内容页面,其中一个 UpdatePanel 中有三个网格,每个网格都有一个单独的刷新按钮。当页面加载时,网格是空的。如果我然后单击每个刷新按钮,一次一个,并在每个步骤之间等待,所有三个网格都将正确填充。

在此页面的第一个版本中,我会在呈现初始页面加载之前预先填充网格。但是,每个网格刷新都很慢,我想改善用户体验 - 初始加载大约需要 30 秒。我想我可以对页面进行 AJAX 化,以便它首先快速加载(使用空网格),然后所有三个刷新都独立于 Javascript 触发,并且每个网格在其各自的刷新调用返回后立即填充,无论它们碰巧是什么顺序准备好。这样,用户不必在至少一些数据可用之前等待所有三个都完成。

如果我只想自动化一个网格的初始填充,我可以很容易地使用这种技术:

if (!IsPostBack)            
    ClientScript.RegisterStartupScript(this.GetType(), "RefreshGridA", "document.getElementById('" + btnRefreshGridA.ClientID + "').click();", true);

当我只想触发一个长期运行的报告时,我已经使用了很多次,它在这里工作得很好。但这是我以前从未考虑过的场景——如果我尝试对多个网格执行此操作:

if (!IsPostBack)            
{
    ClientScript.RegisterStartupScript(this.GetType(), "RefreshGridA", "document.getElementById('" + btnRefreshGridA.ClientID + "').click();", true);
    ClientScript.RegisterStartupScript(this.GetType(), "RefreshGridB", "document.getElementById('" + btnRefreshGridB.ClientID + "').click();", true);
}

...那么唯一完成的刷新是最后一个。我想我不应该感到惊讶,因为如果我手动复制它,然后立即单击一个刷新按钮,我会得到相同的结果 - 第一个 AJAX 调用似乎被放弃了。是这样吗?

甚至有可能完成我想做的事情吗?协调多个独立的同时 AJAX 调用的正确方法是什么?我怀疑我根本不应该使用这些按钮,但是当只涉及一个按钮时,我用这种方法取得了很大的成功。我已经尝试将点击合并到一个脚本中,并且我尝试将每个网格/按钮对包装在它自己的 UpdatePanel 中,但是对于这两种变体,我得到了相同的结果。

4

1 回答 1

0

这里,我找到了一个 javascript 事件队列,可以帮助我做我想做的事:

<script type="text/javascript">
     Sys.Application.add_load(ApplicationLoadHandler)

     function ApplicationLoadHandler(sender, args) {
         var prm = Sys.WebForms.PageRequestManager.getInstance();
         if (!prm.get_isInAsyncPostBack()) {
             prm.add_initializeRequest(InitializeRequest);
             prm.add_endRequest(CompleteRequest);
         }
     }

     var myQueue = new Array();

     function InitializeRequest(sender, args) {
         var prm = Sys.WebForms.PageRequestManager.getInstance();
         if (prm.get_isInAsyncPostBack()) {// if it's working on another request, cache the current item that cause the request
             args.set_cancel(true);
             Array.add(myQueue, args.get_postBackElement());
         }
     }

     function CompleteRequest(sender, args) {
         if (myQueue.length > 0) {// fire corresponding event again of the item cached
             $get(myQueue[0].id).click();
             Array.removeAt(myQueue, 0);
         }
     }

     if (typeof (Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
</script>

这也可以从代码隐藏中呈现,如下所示:

StringBuilder script = new StringBuilder();
script.Append("Sys.Application.add_load(ApplicationLoadHandler)\n");

script.Append("function ApplicationLoadHandler(sender, args) {\n");
script.Append("    var prm = Sys.WebForms.PageRequestManager.getInstance();\n");
script.Append("    if (!prm.get_isInAsyncPostBack()) {\n");
script.Append("        prm.add_initializeRequest(InitializeRequest);\n");
script.Append("        prm.add_endRequest(CompleteRequest);\n");
script.Append("    }\n");
script.Append("}\n");

script.Append("var myQueue = new Array();\n");

script.Append("function InitializeRequest(sender, args) {\n");
script.Append("    var prm = Sys.WebForms.PageRequestManager.getInstance();\n");
script.Append("    if (prm.get_isInAsyncPostBack()) {\n");
script.Append("    args.set_cancel(true);\n");
script.Append("    Array.add(myQueue, args.get_postBackElement());\n");
script.Append("    }\n");
script.Append("}\n");

script.Append("function CompleteRequest(sender, args) {\n");
script.Append("    if (myQueue.length > 0) {\n");
script.Append("        $get(myQueue[0].id).click();\n");
script.Append("        Array.removeAt(myQueue, 0);\n");
script.Append("    }\n");
script.Append("}\n");

script.Append("if (typeof (Sys) !== \"undefined\") Sys.Application.notifyScriptLoaded();");

ClientScript.RegisterStartupScript(this.GetType(), "EventQueue", script.ToString(), true);

不管添加这个队列脚本的方法是什么,我发现我需要给按钮点击添加一点延迟才能让它们排队:

ClientScript.RegisterStartupScript(this.GetType(), "RefreshGridA", "setTimeout(\"document.getElementById('" + btnRefreshGridA.ClientID + "').click();\",100);", true);
ClientScript.RegisterStartupScript(this.GetType(), "RefreshGridB", "setTimeout(\"document.getElementById('" + btnRefreshGridB.ClientID + "').click();\",100);", true);

如果没有 setTimeout,只有最后一个按钮会像以前一样完成刷新。

从根本上说,刷新调用实际上并不是多线程的;它们是连续执行的。但是,我现在对用户体验感到满意。

于 2014-09-12T13:17:21.937 回答