ajax返回jquery ajax执行顺序问题

当前访客身份:游客 [
当前位置:
页面加载完后,会执行10个ajax请求,
$(function(){
查看firebug也是同时有10个ajax请求,按理说,这10个ajax请求,谁先返回结果,谁就执行完成,
但是现在问题是,他们都顺序执行了,第一返回结果后,才执行第二个ajax,依次执行到最后一个。
首先排除$.ajax的async的属性设置问题,
难道是jquery的预加载函数问题,队列顺序执行,不懂这东西。。。不知道什么原因,help。
执行效果如图所示:
1正在执行中
共有5个答案
不是顺序的,我写一个ajax 和一个按钮样式,结果 ajax没结束,样式就显示了
理论上如果是异步模式,那么执行结果是不定(非顺序)的。楼主ajax回调函数是什么。
ajax执行本来就是要有限制的,ie最大并发数好像是2个,其他的例外。对于多个ajax请求,是要用队列的。
以前还专门就这个,自己写过一个执行队列。
引用来自“燕尾蝶”的答案网络通畅,服务器端执行时间相同并无阻塞,就有这种表现
这10个ajax,后台执行所需要的时间有长有短,我调整这10个ajax的顺序,他们依然是顺序返回结果,
第2个ajax可能需要300ms,第3个ajax可能需要100s就执行完了
但是实际效果是,第3个ajax要等第2个ajax执行完成才执行
网络通畅,服务器端执行时间相同并无阻塞,就有这种表现
有什么技术问题吗?
沙逛鱼的其他问题
类似的话题ajax返回顺序问题_百度知道
ajax返回顺序问题
textS+XMLHttpRequest+&#39.serializeArray(),data){
var ajaxData=new Object(),&#47,
;jsonpCallback&
});#login_form&
function login() {
var param = $(&quot,
callback&;
return ajaxData,就是下面login提交的时候总是会空的,
error:data: &
data=ec_ajax(WEB_URL + &quot.done(function(){
/index: function(XMLHttpR
var data=new Object()function ec_ajax(url,param);&#47?app=user&act=login&&#47, errorThrown){
alert('+errorThrown),
writeObj(ajaxData);---&#39: url: function(json){
ajaxData=&#47.ajax({;);
jsonpCallback.php: &quot,我想是顺序问题;;jsonp&failMalert(data):&#39,求救想了好久了;这个data 返回的总是空的 求救
} 问题来了
return ajaxD/}), 这里用个变量保存;writeObj(ajaxData);你在这里return就是有问题的.done(function(){&#47}), 在外面return这个变量
其他类似问题
ajax的相关知识
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁$.ajax同步请求执行顺序,怎么没有等待结果返回,就执行下边语句了?
[问题点数:100分]
$.ajax同步请求执行顺序,怎么没有等待结果返回,就执行下边语句了?
[问题点数:100分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2009年9月 总版技术专家分月排行榜第一
2009年8月 总版技术专家分月排行榜第二
2009年9月 总版技术专家分月排行榜第一
2009年8月 总版技术专家分月排行榜第二
2012年 总版技术专家分年内排行榜第一2007年 总版技术专家分年内排行榜第二2006年 总版技术专家分年内排行榜第二2004年 总版技术专家分年内排行榜第二
2005年 总版技术专家分年内排行榜第三2003年 总版技术专家分年内排行榜第三2002年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第一2007年 总版技术专家分年内排行榜第二2006年 总版技术专家分年内排行榜第二2004年 总版技术专家分年内排行榜第二
2005年 总版技术专家分年内排行榜第三2003年 总版技术专家分年内排行榜第三2002年 总版技术专家分年内排行榜第三
2011年11月 Web 开发大版内专家分月排行榜第三
2011年11月 Web 开发大版内专家分月排行榜第三
2011年11月 Web 开发大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。我们都习惯了 Web 的准动态特性。对于通过单击按钮或链接而发出的每一个请求,浏览器都会发送请求并等待响应。您在该页面上稍作停留,然后再次单击和等待。
正如我在近期专栏中提到的那样,我对 AJAX 模式及其相关技术集所带来的各种可能性感到十分振奋。开发人员和架构师可以构建新一代的网站,其中的准动态模式将替代为更具交互性的结构。我一直喜欢目睹用户第一次体验 AJAX 应用程序的连贯感时的欣喜若狂。
在最近的专栏中,我赞扬了 AJAX 的强大功能,列举了它的许多直接和间接好处。本月我要重点介绍与使用 ASP.NET AJAX Extensions 实现 AJAX 模式直接相关的一些问题。
ASP.NET AJAX Extensions 最初构建于 ASP.NET 2.0 之上,随着 ASP.NET 3.5 的发布,现已全面集成到 ASP.NET 平台上。事实上,ASP.NET AJAX 提供两种编程模型供您选择 — 部分呈现和脚本服务。关于这两种模型的更深入讨论,您可以查阅我在 2007 年 9 月和 2007 年 10 月刊的《MSDN(R) 杂志》上发表的专栏文章。
AJAX 应用程序具有绕过浏览器直接从脚本代码中发出 Web 请求的能力。在使用浏览器请求页面(比如通过标准的“提交”按钮或超链接)时,一次只为每个活动的浏览器窗口处理一个请求。通过脚本请求页面则不受这种限制,多个请求可以同时发生。在 2007 年 7 月期的“领先技术”中,我利用此项功能实现了一个实时进度条,向客户端报告服务器端运行任务的实时进度。从单个浏览器窗口发出并发调用的可能性打开了一个可能解决各种问题的崭新局面,其中包括许多与 UI 相关的问题。
在本月的专栏中,我将评述为基于 ASP.NET AJAX 的 Web 应用程序实现高效用户界面所涉及的问题、解决方案和必要的工具。我会特别关注采用部分呈现模型的应用程序。
AJAX 和用户界面
即使在用户发出 AJAX 请求之后,网页仍会保持活动状态。这意味着用户可以单击活动元素,从而启动可能会干扰当前请求的新操作。因此,同桌面应用程序一样,开发人员有时需要考虑临时禁用部分用户界面。
怎样才能在服务器操作过程中禁用客户端页面元素?有几种方法可以做到这一点。可以获取相应的文档对象模型 (DOM) 元素的 ID,并启用或禁用该元素的状态 — 这是使用 DOM 或 CSS 样式通过脚本实现的客户端操作。另外,ASP.NET 控件特别提供了 Visible 属性。当 Visible 属性设置为 false 时,可阻止服务器控件将其自身标记添加到客户端响应。这样一来,该控件的预定标记就不会在客户端页面中显示。
要禁用和启用 ASP.NET AJAX 中的部分用户界面,首先需要找出该部分所有 HTML 元素的 ID,如下列代码所示:
// Get the reference to the DOM element
var button1 = $get("Button1");
// Disable the status of the element
button1.disabled =
若要禁用某元素,需获取其 ID 并将 disabled 属性设为相应的值。理想的情况是,发出请求之前应立即关闭特定部分的用户界面,请求完成之后立即重新启用该部分用户界面。具体的实现方式将根据您选择的编程模型不同而有所差异。
如果使用部分呈现,请使用 PageRequestManager 对象的事件模型,这个类是部分呈现背后的客户端中枢。完整的类名是 Sys.WebForms.PageRequestManager,其源代码在 MicrosoftAjaxWebForms.js 中定义。PageRequestManager 中包含了设置和控制 AJAX 回发所需的全部逻辑。该类是一个单例 — 这意味着它保证一次只有一个请求挂起。通过下列代码可获得对页面请求管理器的唯一实例的引用:
var manager = Sys.WebForms.PageRequestManager.getInstance();
PageRequestManager 公开了一些客户端事件,通过这些事件可截获 AJAX 回发处理中的关键步骤,详情如图 1 所示。BeginRequest 事件的发生通常是禁用 UI 元素的好机会,EndRequest 事件则是重新启用 HTML 元素的恰当时机。
&Figure 1 PageRequestManager 公开的事件
initializeRequest
InitializeRequestEventArgs
检测到新的 AJAX 请求已发出后立即触发。
beginRequest
BeginRequestEventArgs
刚好在请求发出前触发。
pageLoading
PageLoadingEventArgs
在响应已经全部下载和处理完毕后(但尚未更新页面上的任何内容之前)立即触发。
pageLoaded
PageLoadedEventArgs
在页面上的所有内容刷新后立即触发。
endRequest
EndRequestEventArgs
在所有工作完成后立即触发。
如果您选择脚本服务方法,则可能有一个 JavaScript 驱动的前端,由它与 ASP.NET AJAX 脚本 Web 服务构成的服务器端外层交互。对服务的每个调用都通过一个显式异步脚本调用进行。开发人员对启动远程调用拥有完全控制,并可以安全地禁用 UI 的任何组成部分。因为每个调用都将是异步调用,所以,既可为成功调用也可为失败调用指定一个回调。于是,您可以在回调中将 UI 重置回适当的状态。
总之,有一些与禁用和重新启用 UI 元素相关的问题。我将通过一些场景来深入探讨这些问题。
通过元素 ID 禁用 UI
图 2 显示了在回发过程中用于禁用一个示例 AJAX 页面(使用部分呈现)中某些元素的代码。当页面第一次加载时,BeginRequest 和 EndRequest 事件的处理程序得到注册。pageLoad 函数是一个符合命名约定的处理程序,用于 AJAX 客户端库触发的应用程序加载事件。pageLoad 函数接收两个参数 — 一个是类型 Sys.Application,另一个是 ApplicationLoadEventArgs 对象。
&Figure 2 在回发过程中禁用 UI 的页面
&script type="text/javascript"&
function pageLoad()
var manager = Sys.WebForms.PageRequestManager.getInstance();
manager.add_beginRequest(OnBeginRequest);
manager.add_endRequest(OnEndRequest);
var lcPostbackElementID;
functionw OnBeginRequest(sender, args)
lcPostbackElementID = args.get_postBackElement().id.toLowerCase();
if (lcPostbackElementID === "button1")
$get("Button1").disabled =
function OnEndRequest(sender, args)
if (lcPostbackElementID === "button1")
$get("Button1").disabled =
&form id="form1" runat="server"&
&asp:ScriptManager ID="ScriptManager1" runat="server" /&
&div id="pageContent"&
&b&Enter some data:&/b&&br /&
&asp:TextBox ID="TextBox1" runat="server" /&
&asp:Button ID="Button1" runat="server" Text="Post ..."
onclick="Button1_Click" /&
&br /&&br /&
&asp:UpdateProgress runat="server" ID="UpdateProgress1"&
&ProgressTemplate&
&img src="images/loading.gif" /&
&/ProgressTemplate&
&/asp:UpdateProgress&
&asp:UpdatePanel ID="UpdatePanel2" runat="server"
UpdateMode="Conditional"&
&ContentTemplate&
&asp:Label runat="server" ID="Label1" /&
&/ContentTemplate&
&Triggers&
&asp:AsyncPostBackTrigger ControlID="Button1" /&
&/Triggers&
&/asp:UpdatePanel&
页面中引发的每个 AJAX 回发都会发生 BeginRequest(以及图 1 中列出的所有其他事件)。此类事件只不过通知开发人员正在发出或刚刚完成一个请求而已。这些事件不像(比方说)客户端或服务器按钮的单击事件。您知道即将发生一个回发,但此刻并不知道为什么或哪些 UI 元素对其负责。但是,为了禁用用户界面的相应部分,您需要确切地知道单击的是哪个元素。
伴随 BeginRequest 事件的数据结构中包含了一个对引起回发的 DOM 元素的引用。该成员名为 postBackElement,可通过如下方式访问:
var lcPostbackElement = args.get_postBackElement();
然后即可使用此信息检查用户所单击的元素,并决定哪些元素需要禁用:
if (lcPostbackElement.id.toLowerCase() === "button1")
$get("Button1").disabled =
注意,当恢复原来的 UI 时,此类信息与 EndRequest 事件不发生关联。因些,您需要缓存该引用,或者只缓存该元素的 ID,以便从 EndRequest 事件处理程序中再次检查它。
要禁用和启用 DOM 元素,需要获取该元素的 DOM 引用,然后设置布尔型的 disabled 属性。在 ASP.NET AJAX 中,$get 函数相当于 DOM 的 document.getElementById 调用。更准确地说,$get 相当于一个参数化的 getElementById 调用,它还接受一个可选的引用,以指出要搜索的 DOM 子树的根。
在脚本服务调用中临时禁用 UI 元素十分简单。唯一发生变化的是使用 $get 函数的位置。请在调用前进行禁用,然后在成功和失败回调中重新启用,如图 3 所示。
&Figure 3 在脚本服务调用中禁用 UI 元素
function startCall()
$get("Button1").disabled =
Samples.RemoteService.GetTime(param1, param2,
onCompleted, onFailed);
function onCompleted(results)
// Process response
$get("Button1").disabled =
function onFailed(error)
$get("Button1").disabled =
禁用命名容器中的 UI 元素
此前所讨论的代码完全可以正常工作,但还远谈不上完美。如果需要禁用嵌入母版页或用户控件中的 UI 元素,那又怎么样呢?
许多 ASP.NET 服务器控件使用命名容器为其子控件的 ID 属性值创建唯一的命名空间。对于 GridView 和 Repeater 等模板化和迭代式数据绑定控件而言,这尤其重要。对于每个控件来说,命名容器都是实现了 INamingContainer 接口的最接近的父控件。例如,UserControl 类充当它所容纳的所有控件的命名容器。与母版页关联的页面上的任何控件也存在同样的情况。
对于任何属于命名容器管辖的 ASP.NET 控件来说,其客户端 ID 均更改为采用父级 ID 作为前缀。请考虑以下代码段:
&form runat="server"&
&asp:Button runat="server" ID="Button1" /&
该按钮的客户端 ID 与服务器 ID 相匹配,始终是 Button1。然而,如果您将该按钮移入一个用户控件,或者从一个母版页中派生其内容页面,则此编程方向将立刻发生变化。请考虑以下用户控件:
&%@ Control Language="C#" CodeFile="test.ascx.cs" Inherits="test" %&
&asp:Button runat="server" ID="Button2" Text="Click" /&
将用户控件嵌入一个 ASP.NET 页面后,产生的 HTML 引用了 Button2:
&input type="submit"
name="UserControl1$Button2"
value="Click"
id="UserControl1_Button2" /&
每个所包含控件的 ID 现在都带有父级 ID 作为其前缀。如果只局限于服务器端编程,则此行为对开发人员来说实质上是透明的。但是,如果需要从客户端为 Button2 编写脚本,就需要了解命名容器以及它们如何更改页面 DOM 中 HTML 元素的客户端 ID。
您在图 4 中看到的页面与图 2 显示的页面相同,但它作为内容页面嵌入到母版页中。现在,Button1 的真正客户端 ID 是:
&Figure 4 在回发过程中禁用 UI 的内容页面
&%@ Page Language="C#" AutoEventWireup="true"
CodeFile="DisableUIEmb.aspx.cs"
MasterPageFile="~/Sample.master" Title="Disable UI Elements (Embedded)"
Inherits="Samples_DisableUIEmb" Theme="ProgAjax1" %&
&asp:Content runat="server" ContentPlaceHolderID="ScriptPlaceHolder"&
&script type="text/javascript"&
function pageLoad()
var manager = Sys.WebForms.PageRequestManager.getInstance();
manager.add_beginRequest(OnBeginRequest);
manager.add_endRequest(OnEndRequest);
var lcPostbackElementID;
function OnBeginRequest(sender, args)
lcPostbackElementID = args.get_postBackElement().id.toLowerCase();
if (lcPostbackElementID === "&%= Button1.ClientID.ToLower() %&")
$get("&%= Button1.ClientID %&").disabled =
function OnEndRequest(sender, args)
if (lcPostbackElementID === "&%= Button1.ClientID.ToLower() %&")
$get("&%= Button1.ClientID %&").disabled =
&/asp:Content&
&asp:Content runat="server" ContentPlaceHolderID="ContentPlaceHolder1"&
&div id="pageContent"&
&b&Enter some data:&/b&&br /&
&asp:TextBox ID="TextBox1" runat="server" /&
&asp:Button ID="Button1" runat="server" Text="Post ..."
onclick="Button1_Click" /&
&br /&&br /&
&asp:UpdateProgress runat="server" ID="UpdateProgress1"&
&ProgressTemplate&
&img src="images/loading.gif" /&
&/ProgressTemplate&
&/asp:UpdateProgress&
&asp:UpdatePanel ID="UpdatePanel2" runat="server"
UpdateMode="Conditional"&
&ContentTemplate&
&asp:Label runat="server" ID="Label1" /&
&/ContentTemplate&
&Triggers&
&asp:AsyncPostBackTrigger ControlID="Button1" /&
&/Triggers&
&/asp:UpdatePanel&
&/asp:Content&
ctl00_ContentPlaceHolder1_Button1
要正确地禁用 Button1(或者通常而言,对其编写脚本),就必须知道这个新 ID。虽然可以在外部 JavaScript 文件中查出其名称并对它进行硬编码,但是,确切的 ID 只有在运行时才能得知。图 4 演示了如何使用 ASP 样式的代码块和服务器端 ClientID 属性,在浏览器中产生可解决命名容器问题的参数型脚本代码。图 5 显示了运行中的示例页面。
图 5 使用脚本调整 UI 的内容页面 (单击该图像获得较大视图)
使用 UpdatePanelAnimation 扩展器
被禁用的部分 UI 是特定于回发的,通常使用纯脚本对其进行定义。大多数情况下,您所要做的无非是禁用某些元素;不过,您还可以做更多事情。例如,您可以淡出部分界面,然后再淡入。
如果使用脚本服务方法,则实现此类高级用户交互功能完全是您的责任。然而,如果使用部分呈现方法并安装了 AJAX 控件工具包,则可以依赖一个极棒的扩展器控件:UpdatePanelAnimation 扩展器。
扩展器控件是一种 ASP.NET 服务器控件,它向各种现有服务器控件提供附加的行为。当需要控件的特殊行为时,可在扩展器中编写该行为的代码,然后将该扩展器与原始控件绑定在同一页面中。假设您要在一个文本框中筛选出非数字的字符。您可以开发一个专门的 TextBox 控件,也可以就使用扩展了适当行为的传统纯 TextBox 控件。其优势在于多种类型的控件可以重用相同的行为,而且,还可以自由地组合多种行为,以丰富服务器控件的特定实例。
UpdatePanelAnimation 扩展器旨在向 ASP.NET AJAX 部分呈现页面中的任何可更新区域添加一些动画。当开始进行回发时,您以声明的方式关联页面所要使用的动画。扩展器与基于脚本的动画框架(由 AJAX 控件工具包提供)协同工作。图 6 显示了可用于动态显示可更新区域的示例代码。
&Figure 6 使用 UpdatePanelAnimation 扩展器
&asp:UpdatePanel ID="UpdatePanel1" runat="server"
UpdateMode="Conditional"&
&ContentTemplate&
&asp:Button ID="Button1" runat="server" Text="Load" ... /&
&div id="Panel1"&
&/ContentTemplate&
&Triggers&
&/Triggers&
&/asp:UpdatePanel&
&act:UpdatePanelAnimationExtender ID="UpdatePanelAnimation1" runat="server"
TargetControlID="UpdatePanel1"&
&Animations&
&OnUpdating&
&Sequence&
&EnableAction AnimationTarget="Button1" Enabled="false" /&
&FadeOut AnimationTarget="Panel1" minimumOpacity=".3" /&
&/Sequence&
&/OnUpdating&
&OnUpdated&
&Sequence&
&FadeIn AnimationTarget="Panel1" minimumOpacity=".3" /&
&EnableAction AnimationTarget="Button1" Enabled="true" /&
&/Sequence&
&/OnUpdated&
&/Animations&
&/act:UpdatePanelAnimationExtender&
首先将扩展器绑定到页面中一个特定的 UpdatePanel 控件,然后配置动画。图 6 中的代码在发生回发前(OnUpdating 标记)设置由两个动作组成的序列,在回发完成后(OnUpdated 标记)设置由两个动作组成的另一个序列。EnableAction、FadeOut 和 FadeIn 都是受 AJAX 控件工具包支持的预定义动画。FadeOut 和 FadeIn 使用 CSS 样式淡出和淡入它们所应用的 DOM 子树 — 本示例中的 Panel1。EnableAction 动画只是禁用或启用指定的目标 DOM 元素。
与直接编写脚本相比,UpdatePanel 动画扩展器支持以声明的方式编程,允许您应用更多功能,而不仅仅是禁用元素。不过,扩展器仅局限于使用部分呈现的页面。有关详细信息,请参见 AJAX 控件工具包主页,网址是:。
禁用整个页面
如前所述,要禁用的 UI 部分取决于用户单击的控件,更一般而言,是指所需的操作。但是,在部分呈现环境中,一次只能执行一个请求。只找出和禁用受挂起操作影响的部分界面将付出大量的工作,更重要的是,它不能防止意外的单击。稍后我将更详细地讨论此问题。现在,一句话,禁用整个页面而无需费力找出哪些控件应当禁用是更简单高效的解决方案。
总体构想是创建一个与浏览器的客户端区域同样大小的 DIV 标记,并用它覆盖页面中的全部内容。在这种方式下,任何单击都将由此 DIV 捕获,而不会到达底层的 HTML 元素。您甚至可以将 DIV 与某些样式关联,以便在操作处理过程中禁用页面。图 7 显示了用于完成此任务的 JavaScript 代码。
&Figure 7 用 DIV 覆盖 UI
&script type="text/javascript"&
var _backgroundElement = document.createElement("div");
function pageLoad()
var manager = Sys.WebForms.PageRequestManager.getInstance();
manager.add_beginRequest(OnBeginRequest);
manager.add_endRequest(OnEndRequest);
// pageContent is the parent of the new DIV
$get("pageContent").appendChild(_backgroundElement);
function OnBeginRequest(sender, args)
EnableUI(false);
function OnEndRequest(sender, args)
EnableUI(true);
function EnableUI(state)
if (!state)
_backgroundElement.style.display = '';
_backgroundElement.style.position = 'fixed';
_backgroundElement.style.left = '0px';
_backgroundElement.style.top = '0px';
var clientBounds = this._getClientBounds();
var clientWidth = clientBounds.
var clientHeight = clientBounds.
_backgroundElement.style.width =
Math.max(Math.max(document.documentElement.scrollWidth,
document.body.scrollWidth), clientWidth)+'px';
_backgroundElement.style.height =
Math.max(Math.max(document.documentElement.scrollHeight,
document.body.scrollHeight), clientHeight)+'px';
_backgroundElement.style.zIndex = 10000;
_backgroundElement.className = "modalBackground";
_backgroundElement.style.display = 'none';
function _getClientBounds()
var clientW
var clientH
switch(Sys.Browser.agent) {
case Sys.Browser.InternetExplorer:
clientWidth = document.documentElement.clientW
clientHeight = document.documentElement.clientH
case Sys.Browser.Safari:
clientWidth = window.innerW
clientHeight = window.innerH
case Sys.Browser.Opera:
clientWidth = Math.min(window.innerWidth,
document.body.clientWidth);
clientHeight = Math.min(window.innerHeight,
document.body.clientHeight);
// Sys.Browser.Firefox, etc.
clientWidth = Math.min(window.innerWidth,
document.documentElement.clientWidth);
clientHeight = Math.min(window.innerHeight,
document.documentElement.clientHeight);
return new Sys.UI.Bounds(0, 0, clientWidth, clientHeight);
此处声明了一个 JavaScript 全局变量,用以代表 DIV 标记。初始化完成后,DIV 立刻添加到 DOM 树的指定位置。在这种情况下,它定义为包装整个可见界面的 DIV 标记的子级。BeginRequest 处理程序配置和显示 DIV,从而禁用可见界面。EndRequest 处理程序只是隐藏 DIV,从而恢复 UI:
function OnBeginRequest(sender, args)
EnableUI(false);
function OnEndRequest(sender, args)
EnableUI(true);
DIV 标记固定在 0,0 位置,其宽度和高度采用特定于浏览器的方式动态地计算出来。DIV 的大小反映了浏览器的客户端区域的当前大小。getClientBounds 函数表现了一个脚本编程的示例,它能够解决各种浏览器的对象模型中的差异。
如您所见,代码中使用了一些 Microsoft(R) AJAX 客户端库中内置的类。我借用了 ModalPopup 扩展器源代码中的代码段,该扩展器是 AJAX 控件工具包中最棒的扩展器之一。特别要指出,ModalPopup 扩展器允许页面向用户显示具有模态的内容 — 就是说,阻止用户与页面其余部分交互。实际效果与 window.alert 相同,但界面(即所显示的控件层次结构)完全由您来决定。
图 8 显示了一个使用模式 DIV 在部分呈现操作过程中禁用整个 UI 的页面。
图 8 在部分呈现过程中禁用整个页面 (单击该图像获得较大视图)
一次只允许一个 AJAX 回发
由于部分呈现可让您在不修改编程模型的情况下将 AJAX 功能添加到传统的 ASP.NET 2.0 页面,因而页面的服务器端生命周期得以完全保留。对于回发事件、加载、呈现和视图状态而言均是如此。典型的部分呈现调用的通信量比传统的 ASP.NET 调用的通信量要小一些,但视图状态的大小是固定不变的,只能通过特定于页面的编程技巧加以缩减。
凭借部分呈现,ASP.NET 页面获得了 AJAX 页面的连贯感,但也保留了传统的用户界面。从客户端来看,部分呈现页面表现得如同单一、连续用户界面的一部分。一次只能挂起一个操作,即便从业务角度看两个并发操作是可能的。
假如您有一个页面,显示关于客户的某种信息。此页面包含两个按钮 — 一个用于下载订单信息,另一个用于显示客户详细信息。单纯从业务角度来看,没有任何理由阻止用户依次单击这两个按钮以相继产生两个请求,在第一个请求完成之前即开始第二个请求。这两个请求需要相同的输入 — 客户 ID,而且两者都是只读的,这意味着没有干扰后端数据库状态的任何危险。尽管如此,这两个调用还是不能在部分呈现页面中同时运行,因为部分呈现是基于传统的 ASP.NET 编程模型,即每个请求均返回标记,其中包含整个页面的更新后视图状态。如果您让两个请求同时运行,就会给页面视图状态的一致性带来风险。依次快速发送的两个请求将同一视图状态发送到服务器,但每个请求返回不同的视图状态(根据与请求处理有关的控件得到更新)。这意味着最后一个请求的返回结果将覆盖第一个请求返回时所做的更改。因此,部分呈现 AJAX 页面仍然按照准动态模式工作。
为了避免此类问题,当发出新请求时,页面请求管理器对象自动终止任何挂起的请求。鉴于这种行为,在部分呈现页面中禁用整个 UI 就显得极其重要。这样可以确保用户在当前请求持续期间无法与整个页面进行交互。如您所见,这种说法直接否定了 AJAX 的关键好处之一 — 异步交互。
高优先级调用
在研究部分呈现时会出现一些问题,譬如说,如果出于保持视图状态一致性的需要而不能同时运行两个请求,那么,为什么开发团队没有实现在客户端合并两个部分视图状态的算法?这个问题看似合情合理。然而,这种可能性不存在,视图状态的内部结构至少是部分原因,该结构包括编码的内容、一个哈希值和一个仅限服务器使用的安全值。
在客户端组合两个视图状态从技术上说是可能的,但需要对当前的视图状态结构和 ASP.NET 运行时做出重大更改。而且,事实上让几乎每个人可以获得脚本代码将会带来安全问题,他们可以准备专门的视图状态内容进行重放并实施跨站点脚本攻击。
另一个常见问题与页面请求管理器所实现的后进得胜策略有关,每当收到新请求时它就终止挂起的请求。我发现当某人对编程要点做出决定时,开发人员往往会有被迫的感觉。所以,许多开发人员(包括我自己)似乎不喜欢 AJAX 回发所强加的后进得胜策略。那么,主要让当前的请求得到优先处理,后续的请求要么被取消,要么排队等到第一个请求完成,也就是先进得胜策略如何?
ASP.NET AJAX 框架提供了实现此模式所需的工具,稍后您就会看到。不过,您确信真的需要这种可能性吗?实事求是地说,如果使用部分呈现,就应该准备一次一个请求地传送页面。实现这个目标的最简便且最安全的方法是禁用整个 UI 以防用户单击。
如果出于某种原因,您认为无法禁用整个用户界面,那么,了解如何实现先进得胜的方法也许可以提供您所需要的灵活性。基本构想是编写一些脚本代码以截取每个部分呈现请求的开头部分 — 页面请求管理器的 initializeRequest 事件。在处理程序中,检查运行时状态以确定是否真的要取消请求,然后向管理器发出相应的指示:
function OnInitializeRequest(sender, args)
var manager =
if (manager.get_isInAsyncPostBack() &&
args.get_postBackElement().id === "Button1")
args.set_cancel(true);
该示例代码检查是否正在处理另一个请求,以及这是否为优先级更低的请求。如果是,您可以将事件数据结构中的 cancel 属性设置为 true,从而取消该请求。按照上述代码,最后的请求已取消。不过,您还可以编写代码,为挂起的请求实现一个内部队列。有关高优先级调用的详细信息,请参阅 。
请将您想向 Dino 询问的问题和提出的意见发送至 .
Dino Esposito是 Solid Quality Learning 的一位导师,也是“Introducing ASP.NET AJAX”(ASP.NET AJAX 入门)(Microsoft Press, 2007) 一书的作者。Dino 定居意大利,经常在世界各地的业内活动中发表演讲。您可以通过
与他取得联系,或加入他的博客,网址是:weblogs.asp.net/despos。
Current IssueReceive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.}

我要回帖

更多关于 ajax执行顺序 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信