详谈javascript异步编程
作者:APMNCZT 发布时间:2023-08-23 17:49:53
异步编程带来的问题在客户端Javascript中并不明显,但随着服务器端Javascript越来越广的被使用,大量的异步IO操作使得该问题变得明显。许多不同的方法都可以解决这个问题,本文讨论了一些方法,但并不深入。大家需要根据自己的情况选择一个适于自己的方法。
本文为大家详细介绍js中的异步编程,具体内容如下
一 关于事件的异步
事件是JavaScript中最重要的一个特征,nodejs就是利用js这一异步而设计出来的。所以这里讲一下事件机制。
在一个js文件中,如果要运行某一个函数,有2中手段,一个就是直接调用,比如foo(),第二就是利用事件来触发,这中函数也叫回调函数,比如传递给setTimeout函数和onready属性。
1.setTimeout函数中的事件异步
setTimeout本质上也是一种异步事件,当延迟时间到的时候触发该事件,但是有的有的时候(其实也是大部分时候)都不会按照给定的延迟时间执行,先看下面的代码
var start = new Date();
setTimeout(function() {
console.log('settimeout1:',new Date()-start);
}, 500);
while (new Date() - start < 1000) {
console.log('in while');
}
document.getElementById('test').addEventListener('click', function(){
console.log('test:',new Date()-start);
}, false)
for(var i=0;i<10000;i++){
console.log('in for');
}
setTimeout(function(){
console.log('settimeout2: ',new Date()-start);
},1000);
/* 10214
in while
index.jsp (第 19 行)
10000
in for
index.jsp (第 25 行)
settimeout1: 2263
index.jsp (第 16 行)
settimeout2: 3239
index.jsp (第 28 行)
test: 10006
index.jsp (第 22 行)
test: 28175
index.jsp (第 22 行)
test: 28791
index.jsp (第 22 行)
test: 28966
index.jsp (第 22 行) */
如果按照正常的理解,延迟函数应该在500毫秒之后打断while循环,而事实上并没有,并且,我在while循环和for循环期间点击div时候并没有立即输出test,给出的解释就是:
a)事件队列。调用setTimeout函数的时候,会把传入它的回调函数加入到事件队列中去(事件已经初始化并且在内存了),然后继续执行后面的代码,直到再也没有代码可以运行(没有正常的运行流了,不包括事件函数等异步的内容),就会从事件队列里面pop出一个合适的事件来运行。
b)js是单线程的,事件处理器在线程空闲之前是不会运行的。
2 普通事件的异步和setTimeout类似
二 promise对象和deferred对象
1. promise
promise是一种解决ajax等异步编程回调函数嵌套太多导致代码晦涩难懂的解决方案,特别是在nodejs中,异步无处不在。不同的框架对promise的实现,一下是jquery中的promise的API。
这里不讲promise的实现原理,关于原理在另外的篇幅中介绍。
传统的ajax异步编程是这么写的(jquery1.5之前):
$.get('url', function(){
$.get('url1', function(){
$.get('url2', function(){
}, 'json');
}, 'json');
}, 'json');
这么写代码给开发和维护带来了极大的困难,好在jquery1.5以后引入了promise,就可以这么写了:
$.ajax( "example.php" )
.done(function() { alert("success"); })
.fail(function() { alert("error"); })
.always(function() { alert("complete"); });
现在看上去就明显简单多了。
2.deferred对象
var nanowrimoing = $.Deferred();
var wordGoal = 5000;
nanowrimoing.progress(function(wordCount) {
var percentComplete = Math.floor(wordCount / wordGoal * 100);
$('#indicator').text(percentComplete + '% complete');
});
nanowrimoing.done(function(){
$('#indicator').text('Good job!');
});
三.worker对象和多线程
四.异步脚本加载
1.传统脚本在页面中的位置
脚本分为两大类:阻塞式和非阻塞式。这里的阻塞是指加载阻塞而不是运行阻塞。
<!DOCTYPE html>
<html>
<head>
<script src="headScript"></script>
<script defer src="deferredScript"></script>
</head>
<body>
<script async defer src="chatWidget"></script>
<script async defer src="asyncScript"></script>
</body>
</html>
上面这部分代码是比较标准的关于脚本在一个页面中的位置,1.其中传统的未加任何修饰的headScript是阻塞式的脚本,由于浏览器从上到下解释执行JavaScript,所以这部分脚本文件在一开始就会被执行,并且在执行完之前是DOM是不会渲染的,但是head标签里面的css会加载。2.有defer属性的脚本会在DOM渲染的同时进行加载,但是会在DOM渲染完毕之后才开始执行,不幸的是,不是所有的浏览器都支持defer属性,所以才会有了jquery(function)这个东西。3.同时带有async属性和defer属性时候,defer会覆盖async,但是单独有async的时候,脚本会在DOM渲染的时候加载并且运行。
2.可编程的脚本加载
如果不是一开始就在页面种引入js文件,而是通过用户交互来实现动态的加载js脚本,可以通过编程方式加入。
浏览器获取服务器脚本有2个方法,ajax获取并且通过eval函数执行,另外一个就是在DOM中插入<script>标签,一般用第二种方法,因为浏览器帮助我们生成HTTP请求以及eval会泄露作用域。
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = '/js/feature.js';
head.appendChild(script);
script.onload = function() {
// 现在可以调用脚本里定义的函数了
}
猜你喜欢
- 这篇论坛文章(赛迪网技术社区)主要介绍了一种简单的MySQL数据库安装方法,详细内容请大家参考下文:虽然安装MySQL数据库的文章很多,但是
- 此文章主要向大家描述的是MySQL高级查询方法之记录查询的实际操作步骤,以及对其实际操作过程中要用到的代码的详细描述,以下就是文章的主要内容
- 当服务器必须提供与两个或更多个网络或网络子网的连接时,典型的方案是使用多宿主计算机。此计算机通常位于外围网络(也称为 DMZ、外围安全区域或
- asp之家注:asp中FSO组件的功能很强大,如果没有FSO很难想象ASP会变成什么样。对于学习asp编程的朋友一定会接触到FSO相关的操作
- 表示文字链接最清楚的方式是“蓝色文字+下划线”,这是在浏览器发展过程中形成的。这个问题大家都说过很多次了,我也曾经说过。然而,这样的规范却总
- 我用 ip=Request.ServerVariables
- ASP是目前一种广为应用的用来快速构建动态WEB站点的编程语言,默认的内置开发语言是VBScript,由于ASP和微软Windows系列操作
- 关于导航栏的设计有很多特效,但你浏览过这样一种导航栏特效吗?当鼠标移到导航栏目上时,导航栏目会被一层“
- 前言之前写pandas和matplotlib的时候说到了想要出一期Pyechart系列数据可视化的文章。比起matplotlib,pyeac
- 本文实例讲述了PHP实现基于3DES算法加密解密字符串。分享给大家供大家参考,具体如下:3DES(或称为Triple DES)是三重数据加密
- CSS的学习和其他的学习一样,都需要特定的方法才能比较快的去掌握它.要想掌握CSS, 首先要学会HTML,我刚开始是从零开始学习的
- 工作中遇到一个问题,两个字符串匹配,要求:每个字符串中最多含有一个*,?可以无限多个*代表一个任意长度的字符串,而?则代表一个字符要求可以提
- 代码如下:td=date() '此次为设置当前日期,主要是为了调试方便,实际应用中可以使用当天日期.. str=
- 在备份数据库的时候,数据表中可能存在这样的值array('a'='b','c'='d
- Css3引入了新的盒模型——弹性盒模型,该模型决定一个盒子在其他盒子中的分布方式以及如何处理可用的空间。这与XUL(火狐使用的用户交互语言)
- ASP+javascript实现可显示和隐藏的树型菜单实例:<script language=&qu
- 页面访问慢是网站公认的死穴,如果页面都没法访问,往后再精彩的体验都等于零。这个问题如果专业点说,叫做“加载”呈现效率。那么具体了讲,除常规的
- 在CSS样式中,dl部分只是简单的把内外边距设置为0,dd部分有一个clear属性需要特别注意。当某个元素的属性设置float浮动时,它所在
- 给静态网页加密的方法有很多,有的简单有的复杂。前两天看见有人问静态网页加密问题,就写了这个代码思路:加密时:先把用户的密钥A用md5加密为B
- 这篇论坛文章(赛迪网技术社区)着重介绍了有关SQL注入防御的防御策略及实施步骤,详细内容请参考下文:从去年下半年开始,很多网站被损害,他们在