JavaScript系列之―同步还是异步?

所属分类: 网络编程 / ASP.NET 阅读数: 532
收藏 0 赞 0 分享
从今天开始,我会不定期的写一些关于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();
})
})

这里只是对信号量这个方法进行了简单的阐述。
信号量还支持创建自信号量,如果创建了子信号量,那么父信号量必须等带所有的孩子都归还了信号量之后才可以执行他里面的代码。
由于代码的版权是公司的,所以很抱歉,现在无法给出相应的完整的信号量的实现。
如果下一端我有时间的话,我会给出一个我实现的版本的。
更多精彩内容其他人还在看

解析WPF实现音频文件循环顺序播放的解决方法

本篇文章是对WPF实现音频文件循环顺序播放的方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

解决.net framework 4.0环境下遇到版本不同编译不通过的方法详解

本篇文章是对.net framework 4.0环境下遇到版本不同编译不通过的解决方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

将文件上传、下载(以二进制流保存到数据库)实现代码

将文件以二进制流的格式写入数据库:首先获得文件路径,然后将文件以二进制读出保存在一个二进制数组中具体请祥看本文,希望对你有所帮助
收藏 0 赞 0 分享

点击提交按钮后DropDownList的值变为默认值实现分析

在点击提交按钮后,页面上所有的绑定到数据库的控件值都恢复到默认值,下面与大家分享下DropDownList的值变为默认值
收藏 0 赞 0 分享

ASP.NET web.config中数据库连接字符串connectionStrings节的配置方法

ASP.NET web.config中数据库连接字符串connectionStrings节的配置方法,需要的朋友可以参考一下
收藏 0 赞 0 分享

Linkbutton控件在项目中的简单应用

Button控件可分为button控件、LinkButton控件、ImageButton控件三类,而LinkButton控件则在页面上显示为一个超级链接,下面与大家分享下其具体应用
收藏 0 赞 0 分享

Web.config 和 App.config 的区别分析

Web.config 和 App.config 的区别分析,需要的朋友可以参考一下
收藏 0 赞 0 分享

基于.Net中的数字与日期格式化规则助记词的使用详解

本篇文章是对.Net中的数字与日期格式化规则助记词的使用进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

解决在Web.config或App.config中添加自定义配置的方法详解

本篇文章是对在Web.config或App.config中添加自定义配置的方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

深入本机影像生成器(Ngen.exe)工具使用方法详解

本篇文章是对本机影像生成器(Ngen.exe)工具使用方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享
查看更多