重构JS代码 - 让JS代码平面化

 

js中的嵌套函数用的很多,很牛叉,那为何要平面化?

  • 易懂(自己及他人)
  • 易修改(自己及他人)

平时Ajax调用写法(基于jQuery)

$.post('url', jsonObj,
function (data)
{
if(data)
{
var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation successful!' });
setTimeout(function () { tips.close(); }, 2000);
}
else
{
var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation Failed!' });
setTimeout(function () { tips.close(); }, 2000);
}
}
);

缺点是什么?

  1. 函数嵌套后,理解起来比较吃力
  2. 函数嵌套后,一行函数调用写成了很多行,很容易因为逗号、括号等造成语法错误
  3. jQuery和liger在应用代码中强耦合,要是以后要更换UI框架,需要进行地毯式搜索...

加入延迟特性 - Deferred

var ajaxHandler = $.post('url', params);
ajaxHandler.done(checkServerResponse); var checkServerResponse=function(result)
{
if(result)
{
var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation successful!' });
setTimeout(function () { tips.close(); }, 2000);
}
else
{
var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation Failed!' });
setTimeout(function () { tips.close(); }, 2000);
}
}

释疑:

  1. 改后的js与先前的没有很大区别:如果js采用了OO方式编写,再来看这段代码就很清晰了(可以简单的把checkServerResponse理解为一个private的class方法,这样会很容易理解编写意图)
  2. 要是有多个ajax请求呢?可以写成$.when($.post('url1'), $.post('url2')).done(this.checkServerResponse);类似于合并的意思,并且checkServerResponse函数的参数是2个,分别对应2个ajax请求的result
  3. 要是有多个后续请求呢?可以写成$.when($.post(url)).then(handler1).then(handler2).done(successHandler).always(alwaysHandler).fail(failHandler);

用jQuery的事件来解耦 - 不依赖具体技术

先要注册事件:

$(document).on("saveSuccess", onSaveSuccess);
$(document).on("saveFail", onSaveFail);

然后改造checkServerResponse函数:

var checkServerResponse= function (result) {
if (result)
$(document).trigger("saveSuccess");
else
$(document).trigger("saveFail");
}

好处:

逻辑代码具体不依赖于具体技术,比如上面的onSaveSuccess和onSaveFail,可以是下面的ligerUI:

onSaveSuccess: function () {
var tips = $.ligerDialog.tip({ title: 'Tip', content: 'OK!' });
setTimeout(function () { tips.close(); }, 2000);
},
onSaveFail: function () {
var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Fail!' });
setTimeout(function () { tips.close(); }, 2000);
}

也可以是下面的:

onSaveSuccess: function () {
alert("OK");
},
onSaveFail: function () {
alert("Fail");
},

其实就是接口隔离的原理。

用Pub/Sub模式来解耦 - 不依赖具体技术

这种方式比起上面jQuery原生的事件处理方式更加专业,比如:amplify

使用方式就看基本类似,如下:

amplify.subscribe("saveSuccess", this.onSaveSuccess);
amplify.subscribe("saveFail", this.onSaveFail); checkServerResponse: function (result) {
if (result)
amplify.publish("saveSuccess");
else
amplify.publish("saveFail");
}

amplify比jQuery原生的事件好的地方在于amplify支持优先级,并且可以在订阅函数中控制是否继续执行后续的订阅函数,具体用法大家可以参考amplify官网。

Comet服务器推送与SignalR

 

HTTP协议是一个典型的Request/Response协议,是基于TCP/IP之上的一个应用层协议,该协议最典型的特点就是无状态且需要客户端发起Request服务端才能进行Response,这意味着服务端无法主动“推送”信息。但现代很多应用需求这种“服务端推送”,比如说监控系统、报价系统、游戏、协同文档、进度条等应用。因此本文会谈论服务器推送技术的不同手段,以及在Asp.Net中的SignalR是如何封装这些细节来达到推送的目的。

实现服务器推送的一些手段

由于HTTP协议并不支持全双工,因此目前对于服务器“推送”的手段也是根据HTTP协议的特性玩了很多小花招。但大体上可以分为高端大气的全双工类和略微tricky的长轮询类。Streaming类通常会有比较多的限制,比如说对浏览器的版本要求、需要使用sliverlight或flash等查件来实现全双工等。长轮询类主要是包括长轮询或不间断Ajax请求等。

Ajax定期请求方式

这种方式严格来说并不算是服务器推送,而是客户端在一个比较短的间隔内定期去服务器用Ajax请求信息,如果服务器端有了新的事件,则客户端在下一次请求就会获取到,并在客户端调用对应的回调函数来处理这些信息。简单的示意图如图1所示。

图1.Ajax定期请求

当然,这种方式的一些缺点也是显而易见的,首先定期发起请求会白白消耗服务器资源,其次,这种方式也并不是真正的“实时”。

长连接的方式

长连接是另一种方式,是对于页面挂起一个额外的Ajax请求,当服务器有事件发生时,将请求返回给客户端,并在此挂起一个长连接。从而避免了定期请求的损耗,如图2所示。

图2.长连接方式

这种方式的缺点同样显而易见,就是需要客户端和服务器对于这部分功能写自定义实现代码。

使用插件方式

使用诸如silverlight和flash等插件可以基于socket做全双工的通信,但这种方式需要特定的客户端,跨平台性并不好(比如手机客户端等不支持一些插件,PC端没有预装Silverlight等)。对条件限制比较严格。

Forever iFrame

这种方式本质上和长连接的方法非常类似,就是在页面中嵌入一个iframe元素,该元素的Src属性指向被请求的对象,服务端有事件发生就,就回传一个调用客户端JS方法的JS。Iframe中HTTP头的Transfer-Encoding属性为chunked,这意味着服务端并不知道要发送给客户端多少数据,也就隐式意味着该连接的长度为无限。

HTML5 Web Socket

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 WebSocket通信协议于2011年被IETF定为标准 RFC 6455,WebSocketAPI被W3C定为标准。

在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

WebSocket协议的出现可以避免上述几种方式带来的服务器资源占用和宽带占用。但缺点也是很明显的,对客户端和服务端都有一定要求,包括浏览器的版本和服务器的版本(比如IIS7.5+)

SignalR?

上面说到了这么多中实现实时应用程序的办法,作为Asp.net框架中,提供了一个叫SignalR的框架来封装这些网络细节,SignalR会自动选择合适的实现技术来实现该种实时程序。我们只要关注更高层面的业务实现,而无需关注技术上的实现细节。

SignalR最低需要基于Jquery 1.6.4,在服务端至少需要是.Net FrameWork 4.0+。

使用SignalR会自动根据环境选择合适的网络实现细节,该过程根据微软的官网定义如下:

  1. 如果浏览器是IE8或低于IE8,使用长连接方式。
  2. 如果配置了JSONP参数,则使用长连接方式。
  3. 如果请求跨域,且客户端和服务器端都支持Web Socket,且客户端支持CORS,则使用Web Socket
  4. 如果没跨域,客户端和浏览器都支持的话,使用Web Socket方式
  5. 如果客户端或服务器端不支持Web Socket的话,会使用HTML5的Server-sent events
  6. 如果Server-Sent Event不被支持的话,会使用Forever iFrame
  7. 最后会使用长连接方式

SignalR的实现可以通过在Visual Studio的nuget来获取。SignalR从使用的角度来说模型非常简单,服务端是客户端回调用的HUB方法,而客户端只要引入了对应的JS之后,形成Hub-Proxy,使得服务端被调用后里的方法也可以回调不同的客户端。模型概念如图3所示。

图3.SignalR的Hub模型

在服务端的Hub被调用后,我们可以处理该部分代码,并针对不同的客户端返回信息,一个典型的代码如图4所示。

图4.一些返回给不同客户端的方法

而在客户端,我们仅仅需要引用SignalR的Js文件后,声明了Hub-Proxy,就可以直接调用服务器方法,如图5所示。

图5.客户端直接调用服务端的方法

我们注意到,在使用SignalR的过程中,并没有任何关于网络交互技术细节的实现,仅仅是简单的调用。SignalR已经按照本文之前所提到的那样,根据Context选择的具体的实现细节。

 
 
分类: Asp.net MVC

JS代码平面化的更多相关文章

  1. 重构JS代码 - 让JS代码平面化

    js中的嵌套函数用的很多,很牛叉,那为何要平面化? 易懂(自己及他人) 易修改(自己及他人) 平时Ajax调用写法(基于jQuery) $.post('url', jsonObj, function ...

  2. Firebug调试js代码

    Firebug功能异常强大,不仅可以调试DOM,CSS,还可以调试JS代码,下面介绍一下调试JS. 1.认识console对象 console对象是Firebug内置的对象,该对象可以在代码中写入,可 ...

  3. 浏览器控制台js代码与后台不同步

    原因:浏览器会缓存js 如果是将js代码直接通过<script>标签插入jsp页面中则不存在这个问题 在加载页面的时候会重新加载js代码 如果直接将js代码以文件的形式引入,那么每次在修改 ...

  4. js封装的三级联动菜单(使用时只需要一行js代码)

    前言 在实际的项目开发中,我们经常需要三级联动,比如省市区的选择,商品的三级分类的选择等等. 而网上却找不到一个代码完整.功能强大.使用简单的三级联动菜单,大都只是简单的讲了一下实现思路. 下面就给大 ...

  5. 阻止pc端浏览器缩放js代码

    阻止pc端浏览器缩放js代码 众所周知:移动端页面禁止用户缩放界面只需加上<meta name="viewport" content="user-scalable= ...

  6. 还原网站上压缩的js代码

    还原网站上压缩的js代码 我们经常可以看到一些网站,把所需的javascript代码压缩成一行,就像下图这样 这种代码浏览器能读懂,但正常人是没法阅读的. 既然浏览器能读,浏览器当然也能还原这段代码. ...

  7. 我们为什么要看《超实用的Node.JS代码段》

    不知道自己Node.JS水平如何?看这张图 如果一半以上的你都不会,必须看这本书,一线工程师用代码和功能页面来告诉你每一个技巧点. 都会一点,但不知道如何检验自己,看看本书提供的面试题: 1.     ...

  8. 如何添加商*通新对话快捷链接?不用js代码

    我们在使用商务通一般都是在页面中嵌入一段js代码,如果您是js洁癖,是不是在想着如何直接用一张小图加上商*通新对话链接来代替呢?好,那就一起来研究一下吧. 首先,我们打开一个有商*通js弹窗的页面,比 ...

  9. JS代码判断IE6,IE7,IE8,IE9!

    JS代码判断IE6,IE7,IE8,IE9!2011年12月15日 星期四 14:01做网页有时候会用到JS检测IE的版本,下面是检测Microsoft Internet Explorer版本的三种代 ...

随机推荐

  1. Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same entity解决方法

    1.错误信息 Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUs ...

  2. Topshelf创建Windows服务

    使用Topshelf创建Windows服务 概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps ...

  3. 承诺c指针 (1)指针是地址

    (1)是地址 首先明白一个观点:指针就是地址.这是理解指针的起始一步. 直观感受下.变量的地址 int main() { int foo; int *foo_p; foo = 5; foo_p = & ...

  4. Mono 4 和Jexus 5.6

    Mono 4 和Jexus 5.6 概述 在这篇文章中我们将讨论如何在CentOS 7操作系统,安装 jexus. mono 和 配置 jexus,因此它将能够在这种环境中运行一个asp.net mv ...

  5. KMP算法之从next[]到nextVal[]

    前些日子写了一篇KMP算法的博文,浅谈数据结构之KMP(串中的模式匹配算法),在这片文章中,谈到了一个模式串K值的记录数组 next[],详细可看那篇文章,其实,前面定义的next[]数组是有一定缺陷 ...

  6. —软测试—(5)计算机系统CPU组成

    事实上,我们不得不很早就接触到电脑系统的知识,但仍然会出现不起眼,现象清醒的认识,非常严重丢分. 要我们花功夫去理解,由于非常多东西我们接触不到,比方校验码.码制等.假设你不去理解而是去记,就非常难參 ...

  7. 【Espruino】NO.15 nRF24L01+无线收发器

    http://blog.csdn.net/qwert1213131/article/details/35853747 本文属于个人理解,能力有限,纰漏在所难免,还望指正! [小鱼有点电] [Espru ...

  8. jQuery组织您钞四----jQuery操作DOM

    一.采用jQuery创建节点 节点是DOM基础设施.依据DOM产品规格,Node是一个很宽泛的概念,包含元素.属性.正文.档..实际开发过程中,要创建动态内容,主要操作的节点包括元素. 属性和文本. ...

  9. SSH深度历险记(两) Jboss+EJB一审

    学习感悟:每次学习新知识.通过初审会从小事做起,获得成就感.经典Hello Workd我们成功的例子奠定了门哈,呢.非常好的理解了.Ejb的核心. 今天主要以这个小实例,来学习EJB的分布式,我们能够 ...

  10. 优秀个人免费私有云OwnCloud 8.0终于发布 - 亮眼新功能初探简介

    OwnCloud是一个基于Linux的私有云开源项目,用户可以免费使用它来搭建自己的私有云来进行文件和多媒体等的分享. 本人有幸在大概一年多前因为项目需要而接触和使用到OwnCloud,但不幸的是当时 ...