一 同步与异步

在说异步和同步之前,先考虑到以下大家熟悉的场景:

10个人去银行办理业务,银行只有一个窗口,大家有秩序的叫号排队,其中2个人:A B 需要填写很多表单,所以耗时很长。为了处理这10个人的业务,产生两种如下的两种方案:

1. 方案1:

大家的业务必须严格按照叫号的顺序排队执行,前一个人的业务全部办理完成后,后一个才能办理。

2. 方案2:

刚开始大家也是按照叫号的顺序来办理业务,当排到A的时候,前台会把她需要填写的表单给她,让她去一旁填写,然后A后面的人接着上来办理业务。排到B的时候也是这样。当A或者B将表单填写完成后,会站到一个等候区,待当前窗口的那个人办理完业务后,处于等候区的A或者B前去办理业务(这时候A B的顺序取决于谁先将单子填完)

3. 两种方案的思考:

很显然,方案一会造成时间上的浪费,相反,方案2会提升效率;

回到当初的话题上来,方案一就是典型的同步,方案二就是异步,也称非阻塞,方案一中,当A/B填写表单的时候,柜台人员无事可做,造成同步状态下的主程序空闲。柜台人员一次只能处理一个人的业务,就对应着JS单线程,柜台人员把表单给A或者B可以理解为注册发送Ajax请求,A/B填写表单的过程,也就是:服务器处理请求,返回数据的时间段。但是在这段时间内,柜台人员同样可以处理后面人的业务,这就形成了典型的异步场景。

人们排队的区域,相当于JS中的主线程。A/B填写完表单后,站在的等候区,相当于JS中的任务队列;

4. 一个简单的异步与任务队列的案例

var start = new Date;
setTimeout(function(){
var end = new Date;
console.log('Time elapsed:', end - start, 'ms');//输出值为1001ms
}, 500);
while (new Date - start < 1000) {};

简单解读:首先程序声明一个定时器,在500ms后执行一个匿名回掉。在注册完该定时器之后,主程序会接着向下执行。while循环会持续占据主程序1000ms的时间。由于JS的单线程,并且该任务为同步任务,所以这段时间内,主程序不会执行其他操作,也即:主程序被阻塞。这段时间里,定时器已经被浏览器内核相应的模块执行完成,回掉函数已经放到任务队列中。待主程序空出的那一刻,匿名回掉被执行,打印时间。

注:主程序即JS单线程处理程序,即JS引擎,由浏览器内核提供。任务队列是独立于主程序的。


二  Event Loop

在单线程的Javascript引擎中,setTimeout()是如何运行的呢,这里就要提到浏览器内核中的事件循环模型了。简单的讲,在Javascript执行引擎之外,有一个任务队列,当在代码中调用setTimeout()方法时,注册的延时方法会交由浏览器内核其他模块(以webkit为例,是webcore模块)处理,当延时方法到达触发条件,即到达设置的延时时间时,这一延时方法被添加至任务队列里。这一过程由浏览器内核其他模块处理,与执行引擎主线程独立,执行引擎在主线程方法执行完毕,到达空闲状态时,会从任务队列中顺序获取任务来执行,这一过程是一个不断循环的过程,称为事件循环模型。

三 异步与单线程

关于异步与单线程的区别和联系,在网站上看到一个比较清晰的解答,特记录在此:

JS的单线程是指一个浏览器进程中只有一个JS的执行线程,同一时刻内只会有一段代码在执行(你可以使用IE的标签式浏览试试看效果,这时打开的多个页面使用的都是同一个JS执行线程,如果其中一个页面在执行一个运算量较大的function时,其他窗口的JS就会停止工作)。
而异步机制是浏览器的两个或以上常驻线程共同完成的,例如异步请求是由两个常驻线程:JS执行线程和事件触发线程共同完成的,JS的执行线程发起异步请求(这时浏览器会开一条新的HTTP请求线程来执行请求,这时JS的任务已完成,继续执行线程队列中剩下的其他任务),然后在未来的某一时刻事件触发线程监视到之前的发起的HTTP请求已完成,它就会把完成事件插入到JS执行队列的尾部等待JS处理。又例如定时触发(settimeout和setinterval)是由浏览器的定时器线程执行的定时计数,然后在定时时间把定时处理函数的执行请求插入到JS执行队列的尾端(所以用这两个函数的时候,实际的执行时间是大于或等于指定时间的,不保证能准确定时的)。
所以,所谓的JS的单线程和异步更多的应该是属于浏览器的行为,他们之间没有冲突,更不是同一种事物,没有什么区别不区别的。




参考文章:

阮一峰 :http://www.ruanyifeng.com/blog/2014/10/event-loop.html

Alloy Team:http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout-said-the-event-loop-model/

http://blog.csdn.net/softwarenb/article/details/52138363






本文转载:CSDN博客