同步异步深入理解

2018-11-27  本文已影响0人  暖年的咆哮

JS是“单线程”的,所以处于这个线程上的所有任务,都会一个一个依次执行,所以在某些特殊情况下,例如ajax请求等,就会造成请求如果时间太长,导致后续任务一直在等待,页面不加载等问题出现,所以就出现了异步的概念。

同步和异步的差别就在于这条流水线上各个流程的执行顺序不同。

最基础的异步是 setTimeout() 和 setInterval() 函数,很常见,但是很少人有人知道其实这就是异步,因为它们可以控制JS的执行顺序。我们也可以简单地理解为:可以改变程序正常执行顺序的操作就可以看成是异步操作。如下代码:

                <script>
                    console.log( "1" );
                    setTimeout(function() {
                        console.log( "2" )
                    }, 0 );
                    setTimeout(function() {
                        console.log( "3" )
                    }, 0 );
                    setTimeout(function() {
                        console.log( "4" )
                    }, 0 );
                    console.log( "5" );
                </scripe>
                //1,5,2,3,4

可见,尽管我们设置了setTimeout(function,time)中的等待时间为0,结果其中的function还是最后执行。
所以在最初的JS设计者中有了一个任务队列的概念:

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

于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是,不进入主线程、而进入"任务队列"(taskqueue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。

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

所谓"回调函数"(callback),就是那些会被主线程挂起来的代码,异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。例如ajax的success,complete,error也都指定了各自的回调函数,这些函数就会加入“任务队列”中,等待执行

上一篇下一篇

猜你喜欢

热点阅读