当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > JavaScript系列之―同步还是异步?

ASP.NET
Script:WINDOWS Script 枚举运行中进程
使用Flex结合Webservice完成域名查询
VSTS Team System 总算装好了。
用于部署数据库的 数据库初始化工具 xzSQLDeploy Tools V1.0 (for SQLServer) f...
一个将阿拉伯数字转换成中文大写的最简单算法
SCRIPT:使用Windows Script 关闭和打开指定程序
Script:使用WINDOWS脚本访问WEB SERVICES
asp.net连接Access数据库
VB中IIS Application发布可能出现的问题
VB打包后的安装问题
Nhibernate的数据分页技术(续)
使用API函数复制文件,可显示进度。
VB打包技巧
VB.NET实现DirectSound9 (9) 实现示波器
VB.NET 实现DirectSound9 (10) 均衡器
[水晶报表部署系列之一]轻松搞定水晶报表9.2打包
DataGrid 中双向排序的一种办法
利用System.EventHandler来实现两个窗体间的事件调用
多线程应用程序中调用窗体的一点心得
Smart Client之旅一:用B/S方式运行Exe应用程序

ASP.NET 中的 JavaScript系列之―同步还是异步?


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 119 ::
收藏到网摘: n/a

从今天开始,我会不定期的写一些关于JavaScript的东西,包括语言,应用等方面。组成JavaScript系列。
如果没有特殊的说明,这里假定JavaScript的执行环境是在浏览器(browser)当中的。
今天开始第一次,讨论一下同步和异步。
曾经查询过一些JavaScript的信息,发现google出来的结果都是询问JavaScript如何能够实现异步的代码。
而我,很不幸,查询的却是如何让JavaScript实现异步调用的同步(是不是挺起来很诡异)。
首先说一下JavaScript当中的异步方法。
其实这个问题是大家经常要碰到的。而且这个实现也很简单。我就不多说了。
给两段代码
setTimeout方法,他让你的代码在指定的时间(毫秒)之后执行指定的方法。只执行一次。
比如:
alert(1);
setTimeout(”alert(2)”, 1000);
alert(3);
代码在执行到setTimeout的时候,会继续执行下面的代码(alert(3))而不会被阻塞。等待1000ms之后执行alert(2)
setInterval方法,他让你的代码每隔指定的时间,执行指定的方法,直到调用clearInterval
比如:
alert(1);
timer = setInterval(”alert(2)”, 1000);
alert(3);
代码基本上和上面的相同,不同的是,每隔1000ms就会执行一次alert(2),直到调用
clearInterval(timer);
我们应该注意到setTimeout和setInterval都是window的方法。
我们可以直接使用,但是规范的还是调用window.setTimeout window.setInterval,之所以提及这个,我会在以后的JavaScript系列中继续讲解。
现在该说一下我遇到的问题了。
我现在使用dwr作为AJAX的server端引擎,在调用dwr方法的时候,需要提供一个回调方法(callback function)来接受server的返回结果。
而这个回调方法是不会被阻塞的。此时browser回启动另外的现成处理。
这个很好理解,因为dwr的这个方法执行的时间是无法预料的,如果此时调用被阻塞,而server又花相当长的时间进行处理。那么浏览器就会死在这里。从用户体验的角度是根本无法接受的。
这里的例子代码是

ServerHandler.getString(”Weiming”, function (str) { //”Weiming”是传回server的参数
alert(str);
}); // ServerHandler是dwr提供的server方法的interface,具体使用请参见dwr网站。
alert(1);
在执行的过程中,会先执行alert(1),然后在一个无法预料的时间后执行alert(str)。
如果一次简单的比如hello world的调用是不会出问题的。
但是如果我要执行的一系列的dwr function是有前后顺序的,比如后面执行的需要前面的返回结果,简单的代码书写顺序是无法保证执行顺序的。
var myID = null;
ServerHandler.getID(function (id) {
myID = id; //无法预料何时会执行这句话
});
ServerHandler.getUserWithID(myID, function (name) {
/*
此时myID还没有值,因为上面的 myID = id这段代码是需要一个时间段之后才会执行的
*/
alert(”hello:” + name);
});
比如这样的代码就会出错。那么如何解决呢?
最简单的实现方法就是callback function的嵌套。

ServerHandler.getID(function (id) {
ServerHandler.getUserWithID(id, function (name) {
alert(”hello:” + name);
}
});
这样我们就可以保证多个dwr方法调用的顺序了。这样貌似解决了问题。但是并不完美。
原因是当我们把JavaScript和Browser作为一个操作的平台和逻辑业务的平台(AJAX的应用程序,后面的JavaScript系列中会有提及),而不是一个简单的展示平台的时候。这样的回调函数嵌套就很难控制了。
这也就是我最开始指出的需要同步异步调用的一个方法。
最终我在公司的解决方案是这样的。
写一个信号量的类(JavaScript的面向对象会稍后讲解),当我需要执行一个方法的时候,我就申请一部分信号量。
把需要被执行的方法放进信号量的队列进行等待。等前面等待的方法(如果存在)执行后在执行。
信号量将作为一个参数被传入执行的方法,这样这个方法可以决定释放这个信号量还是继续分发。
比如
var s = new Semaphore();
var myID = null;
s.p(function (e) { //把方法放入信号量队列
ServerHandler.getID(function (id) {
myID = id;
s.v(); //释放信号量
}
});
s.p(function (e) { //将第二个方法放到信号量队列,只有当前面的s.v()执行之后,这个方法才会执行。
ServerHandler.getName(myID, function (name) { //此时,可以保证myID一定有值
alert(”Hello:” + name);
s.v();
})
})
这里只是对信号量这个方法进行了简单的阐述。
信号量还支持创建自信号量,如果创建了子信号量,那么父信号量必须等带所有的孩子都归还了信号量之后才可以执行他里面的代码。
由于代码的版权是公司的,所以很抱歉,现在无法给出相应的完整的信号量的实现。
如果下一端我有时间的话,我会给出一个我实现的版本的。