我有一个ASP内容页面,在一个UpdatePanel中有三个网格,并且每个网格都有一个单独的刷新按钮。页面加载时,网格为空。如果我然后单击每个刷新按钮,一次一个,并在每个步骤之间等待,所有三个网格将正确填充。
在我的第一个版本的本页中,我会在渲染初始页面加载之前预先填充网格。但是,每个网格刷新都很慢,我想改善用户体验 - 初始加载大约需要30秒。我以为我可以AJAXify页面,以便它首先快速加载(使用空网格),然后所有三个刷新都是独立于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中,但我对这两种变体都得到了相同的结果。
答案 0 :(得分:0)
从here,我找到了一个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,只有最后一个按钮会像以前一样完成刷新。
从根本上说,刷新调用实际上并不是多线程的;它们是连续执行的。但是,我现在对用户体验感到满意。