一 同步与异步
在说异步和同步之前,先考虑到以下大家熟悉的场景:
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
三 异步与单线程
关于异步与单线程的区别和联系,在网站上看到一个比较清晰的解答,特记录在此:
参考文章:
阮一峰 :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