浅谈JavaScript的【同步】VS【异步】!!!

                                                            【书山有路勤为径,学海无涯苦作舟】

谈到JavaScript的【同步】和【异步】之前不得不先说一说JavaScript,接下来是对JavaScript特性的一点理解:

       JavaScript一种直译式脚本语言,是一种动态类型弱类型基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。

      1、脚本语言    ----    脚本语言是为了缩短传统的编写-编译-链接-运行(edit-compile-link-run)过程而创建的计算机编程语言,只在被调用时进行解释或编译,然后执行。它的命名起源于一个脚本“screenplay”,每次运行都会使对话框逐字重复。早期的脚本语言经常被称为批量处理语言或工作控制语言。

       2、动态语言    ----    动态语言, 程序在运行时可以改变其结构;新的函数可以被引进,已有的函数可以被删除等在结构上的变化。JavaScript便是一个动态语言。除此之外如Ruby、Python等也都属于动态语言,而C、C++等语言则不属于动态语言。比如在JavaScript中可以在对象定义之后动态的为其添加属性和方法:

       3、弱类型    ----    强/弱类型指的是语言类型系统的类型检查的严格程度,弱类型的语言在声明变量的时候不必进行变量类型的确定,语言在运行时会隐式做数据类型转换,对于弱类型语言来说,不同类型的变量可以进行直接运算,而强类型的则不可以。

--------------------------------------------------------------------【同步】VS【异步】--------------------------------------------------------------

JavaScript语言是一门“单线程”的语言,不像java语言,类继承Thread再来个thread.start就可以开辟一个线程,所以,javascript就像一条流水线,仅仅是一条流水线而已,要么加工,要么包装,不能同时进行多个任务和流程。

扫描二维码关注公众号,回复: 3010541 查看本文章

举例说明:【同步】比如我们去购物,如果你去商场实体店买一台空调,当你到了商场看中了一款空调,你就向售货员下单,售货员去仓库帮你调配物品,但是这天你热的实在不行了,就催着商家赶紧给你配送,于是你就等在商场里候着他们,直到商家把你和空调一起送回家,一次愉快的购物就结束了。这就是同步调用。

【异步】如果我们赶时髦,就坐再家里打开电脑,在网上订购了一台空调,当你完成网上支付的时候,对你来说购物过程已经结束了。虽然空调还没有送到家,但是你的任务都已经完成了。商家接到你的订单后,就会加紧安排送货,当然这一切已经跟你无关了,你已经支付完成,想干什么就能去干什么了,出去溜达几圈都不成问题。等送货上门的时候,接到商家电话,回家一趟签收即可。这就是异步调用。    (注:以上【同步】【异步】举例说明 内容摘自Java高并发程序设计)

实例说明:其实最基础的异步是setTimeoutsetInterval函数,很常见,但是很少有人知道其实这就是异步,因为它们可以控制js的执行顺序。我们也可以简单地理解为:可以改变程序正常执行顺序的操作就可以看成是异步操作。

如下代码:

输出顺序是?

  可见,尽管我们设置了setTimeout(function,time)中的等待时间为0,结果其中的function还是后执行。

火狐浏览器的api文档有这样一句话:Because even though setTimeout was called with a delay of zero, it's placed on a queue and scheduled to run at the next opportunity, not immediately. Currently executing code must complete before functions on the queue are executed, the resulting execution order may not be as expected。

意思就是:尽管setTimeout 的time延迟时间为0,其中的function也会被放入一个队列中,等待下一个机会执行,当前的代码(指不需要加入队列中的程序)必须在该队列的程序完成之前完成,因此结果可能不与预期结果相同。

这里说到了一个“队列”(即任务队列),该队列放的是什么呢,放的就是setTimeout中的function,这些function依次加入该队列,即该队列中所有function中的程序将会在该队列以外的所有代码执行完毕之后再依次执行,这是为什么呢?因为在执行程序的时候,浏览器会默认setTimeout以及ajax请求这一类的方法都是耗时程序(尽管可能不耗时),将其加入一个队列中,该队列是一个存储耗时程序的队列,在所有不耗时程序执行过后,再来依次执行该队列中的程序。

又回到了最初的起点——javascript是单线程。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。于是就有一个概念——任务队列。如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。于是JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备和挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头把挂起的任务继续执行下去。

于是,所有任务可以分成两种,一种是同步任务(synchronous)另一种是异步任务(asynchronous)同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。

具体来说,异步运行机制如下:

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。  

"任务队列"是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。
"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等),比如$(selectot).click(function),这些都是相对耗时的操作。只要指定过这些事件的回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。
所谓"回调函数"(callback),就是那些会被主线程挂起来的代码,前面说的点击事件$(selectot).click(function)中的function就是一个回调函数。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。例如ajax的success,complete,error也都指定了各自的回调函数,这些函数就会加入“任务队列”中,等待执行。

                                                                                     本文思想来源:http://www.cnblogs.com/c3gen/p/6170504.htm  

                                                                                                                                                【待大神指点不足】...

猜你喜欢

转载自blog.csdn.net/T_SmileEyes/article/details/81104207