一、背景说明
随着公司BS产品发布越来越多,开发人员比较紧张,原CS系统开发人员也主动的学习BS系统的开发,并且参与维护开发。
但CS系统和BS系统还是有一些比较大的差异的,特别是思维上要进行一些转变,否则的话,可能会出现代码看着是正确的,但运行出来的效果就有问题。或者最终效果也实现了,也知道怎么写代码,但是没有理解为什么要这样写。
所以打算把我自己的理解整理出来,跟大家一起讨论一下,让大家对这个原理理解更清楚一些。
二、界面初始展示执行步骤
下面我们假设用户已经登录系统,点击操作员维护菜单,马上进入到操作员列表界面为例进行说明
1、CS界面初始同步展示执行步骤
从上面的流程可以看出,除了查询操作员的sql语句或存储过程是在数据库服务器中执行外,我们写的所有业务代码都是直接在CS程序所在电脑中运行的。
并且这个执行过程是单线程顺序执行的,sql语句查询缓慢会直接导致操作员列表窗体的展示不出来,要等待数据最终查询完成,返回数据,并且绑定到数据窗口后才能正常展示。
2、BS界面初始同步展示执行步骤
从上面的流程可以看出,从用户点击操作员维护菜单开始,浏览器就会一直显示一个加载中的空白页面,此时请求会到达服务器(主要业务代码都是在web服务器上进行执行),服务器查询数据(sql语句在数据库服务器中执行),并且最终生成完整的html后(生成html代码也是在web服务器上执行),一起返回给浏览器,再由浏览器来呈现界面(此时浏览器只是简单的渲染,不涉及业务代码或者少量的js代码的执行)。
在整个这个过程中,用户只能等待,并且也都是串行执行的。如果数据库或者web服务器执行比较慢的话,则页面会一直呈现一个白色的空白页面,用户体验不好。
为了解决界面初始化加载时,用户等待的时候,一般会选择将同步更改为异步,详见下面的说明。
3、CS界面初始异步展示执行步骤
异步和同步的最大区别就是,用户看到界面的时间,用户可以在极短的时候内就先看到界面(生成界面的代码也是在CS系统电脑中运行),但数据仍然是显示加载中,让用户心里不会那么着急。
等数据在单独的线程中加载完成(查询数据sql或存储过程在数据库服务器中执行)后,再显示到用户界面中(线程查询数据代码,更新界面代码都是在CS系统电脑中运行),供用户查看和操作。
这种编程相对于同步来说,更复杂一些,多了线程操作,线程切换等。
4、BS界面初始异步展示执行步骤
异步和同步的最大的区别就是用户等待空白页面的时间,同步是一直等待到页面全部完成。而异步时,则是先显示页面给用户,再异步加载数据后进行显示。
从上述执行过程中可以看到:
- 页面的编译和执行是在web服务器中执行(Web服务器中执行)
- 然后执行逻辑返回到浏览器中,浏览器执行执行js脚本来异步加载数据(浏览器中执行)
- 此时服务器收到新的请求后又开始在web服务器中执行数据查询的代码(Web服务器中执行)
- 并且将sql或者存储过程发送给数据库服务器,在数据库中进行执行。(数据库中执行)
- 数据返回到web服务器后,进行一定的处理后(Web服务器中执行)
再进一下的返回给浏览器,此时浏览器再执行js脚本,将数据展现出来。(浏览器中执行)
三、用户操作执行步骤
下面以用户点击修改某个操作员为例,说明一下用户操作时的执行步骤。
用户操作时,CS中基本都是同步操作的,所以只讲同步操作的执行步骤,异步的只是将事件的代码放到单独线程中执行,不再特别说明。
BS中基本都是异步操作的,同步操作的话和BS界面初始展示的执行步骤相同,所以下面只讲异步操作的执行步骤。1、CS用户操作同步执行步骤
从上面的执行流程中可以看出,和界面初始化的执行步骤基本相同。除查询操作员数据是在数据库中执行外,其他代码都是在CS程序所在电脑运行。
2、BS用户操作操作异步执行步骤
执行过程如下:
显示对话框
- 可以直接显示(如果结构已经加载)(浏览器中执行)
- 异步加载结构
- 服务器编译并执行页面或控制器,并且返回局部视图(Web服务器中执行)
- 浏览器渲染并显示页面(浏览器中执行)
- 异步加载操作员数据(浏览器中执行)
- 准备查询操作员数据(Web服务器中执行)
- 查询操作员数据(数据库中执行)
- 处理数据库返回的操作员数据并返回给浏览器(Web服务器中执行)
-
四、如何区分BS视图中的代码是在web服务器中执行还是浏览器中执行?
1、Razor视图
1. 在web服务器中执行的代码
1.1.以@符号开头的代码
@ViewBag.ShortTitle <a href="javascript:_reloadMvcCaptchaImage()"><img src="@Url.Action("LoadCheckCode",new { r=DateTime.Now.Ticks})" alt="@GlobalResource.正在加载..." title="@GlobalResource.刷新图片" width="90" height="32" border="0"></a> <script type="text/javascript"> var CommonValues = { TryHotelId: "@Model.TryHotelId", TryUserName: "@Model.TryUserName", TryUserPass: "@Model.TryUserPass", AuthLogin: "@Url.Action("AuthLogin")", GetBanner: "@Url.Action("GetBanner", "Account")", Logout: "@Url.Action("Logout")", LoadCheckCode: "@Url.Action("LoadCheckCode")", GetServicePhone: '@Url.Action("GetServicePhone", "Account")', GetCompanyName: '@Url.Action("GetCompanyName", "Account")', GetCompanyInfo:'@Url.Action("GetCompanyInfo", "Account")', }; </script>
1.2.包含在@{}中的代码
@{ Layout = null; var product = ViewBag.product as Gemstar.BSPMS.Common.Services.Entities.M_v_products; var currentNeutralUICulture = Gemstar.BSPMS.Hotel.Web.Models.CultureHelper.GetCurrentNeutralUICulture(); var sysShortName = currentNeutralUICulture == "en" ? product?.SysShortEName : product?.SysShortName; ViewBag.Title = sysShortName; var domain1 = product.Domain; var domain2 = product.Domain2; string accessDomain = ViewBag.domain; string changeDomain = domain1; if (accessDomain.Contains(domain1)) { changeDomain = domain2; } var protocol = ViewBag.Protocol; } @if (!MvcApplication.IsTestEnv) { <script type="text/javascript">var loginUrl = "@string.Format("{0}{1}", protocol, accessDomain)"; if (window.top != window) { window.top.location = loginUrl; }</script> }
2.在浏览器中执行的代码
除了上述特殊标记的代码外,其余代码都是原样返回到浏览器中由浏览器进行渲染和执行。
需要执行的js代码,需要包含在