1.背景介绍
2.知识剖析
3.常见问题
4.解决方案
5.编码实战
6.扩展思考
7.参考文献
8.更多讨论
1.背景介绍
由于javascript语言是一门“单线程”的语言,所以,javascript就像一条流水线,仅仅是一条流水线而已,要么加工,要么包装,不能同时进行多个任务和流程。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。于是就有一个概念——任务队列。如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。于是JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。于是就有一个概念——任务队列。如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。于是JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
那么这里说的同步和异步到底是什么呢?js官方的文档在使用这两个词的时候并不准确,包括其他文档和很多其他词汇,都只是听起来高深,但实际应用好像跟这些词没半毛钱关系。例如“路由”这个词,不知道的人从字面意义上谁又能说出“路由”是什么意思呢?倒是路由器在生活中经常遇到不会感到陌生,将route使用谷歌翻译之后,其实就是路径和线路的意思,这样路由的概念也就跃然于脑海之中了,也就是说遇到陌生的概念和词汇,大可不必惊慌失措,重要的是理解其背后的本质
同步和异步的概念
“同步”—— 一下就让人想到“一起”这个词;“异步”呢,从字面来讲,好像是在不同的(异)的ways上do something,那首先想到的词可能是“一边...一边...”,比如‘小明一边吃雪糕一边写作业’,这完全没毛病,雪糕吃完了,作业也写完了,这就是异步?这种解释十分表面,停留在这个层面显然是不够的 无论如何,做事情的时候都是只有一条流水线(单线程),同步和异步的差别就在于这条流水线上各个流程的执行顺序不同。 可以简单地理解为:可以改变程序正常执行顺序的操作就可以看成是异步操作。例如setTimeout和setInterval函数,Ajax通信等
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务,ok,这不难理解;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复
回调函数
所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应,异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。例如ajax的success,complete,error也都指定了各自的回调函数,这些函数就会加入“任务队列”中,等待执行。
回调函数,同步,异步,单线程,任务队列,事件循环,这么多吓人的概念,彼此的关联又是如此的紧密,得想个办法把这些串起来,并进行总结梳理.
在公路上,汽车一辆接一辆,有条不紊的运行。这时,有一辆车坏掉了。假如它停在原地进行修理,那么后面的车就会被堵住没法行驶,交通就乱套了。幸好旁边有应急车道,可以把故障车辆推到应急车道修理,而正常的车流不会受到任何影响。等车修好了,再从应急车道回到正常车道即可。唯一的影响就是,应急车道用多了,原来的车辆之间的顺序会有点乱。
同步可以保证顺序一致,但是容易导致阻塞;异步可以解决阻塞问题,但是会改变顺序性。改变顺序性其实也没有什么大不了的,只不过让程序变得稍微难理解了一些。
约会结束后你送你女朋友回家,离别时,你肯定会说:“到家了给我发条信息(call me back),我很担心你。” 对不,然后你女朋友回家以后还真给你发了条信息。小伙子,你有戏了。其实这就是一个回调的过程。你留了个参数函数(要求女朋友给你发条信息)给你女朋友,然后你女朋友回家,回家的动作是主函数。她必须先回到家以后,主函数执行完了,再执行传进去的函数,然后你就收到一条信息了。
回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。
参考一: JavaScript 运行机制详解:再谈Event Loop
参考二: js中的同步和异步的个人理解
感谢大家观看
By 严泽浩丨曾健