在了解JQuery的异步队列实现之前,有必要去了解javascript的异步模型.
Javascript的异步其实并不算严格意义上的异步,js的异步是指让某段代码片段在将来再执行,而不是让执行流不必等待继续向下进行.
在多线程的语言中最容易想到的异步方式就是在当前线程中,新创建一个线程让某段代码片段运行在新创建的线程中,从而使当前线程继续向下进行.
而任何一本书关于js的书都会告诉我们js是运行在单线程里的,这个线程称为UI线程,从名字就知道这个线程不光用于运行js代码,还负责事件的处理和UI的绘制.
在游览器内部维护着一个事件队列,触发的事件会一个个的放进这个队列中,UI线程在空闲时会去查看这个队列,如果队列不为空,就取第一个事件并执行其监听函数.
for (var i = 0; i < 3; ++i) { setTimeout( function(){ console.info( 'setTimeout: ' + i); }, 0); console.info( 'for循环: ' + i) }
上面这段代码在UI线程的执行示意图图如下
首先将此段js代码放进UI线程中执行,当代码执行到setTimeout(fn, mills)时,游览器会在事件队列中放入此定时事件1,前面说过只有当UI线程空闲时才会去执行定时事件,但此时js代码还在执行,所以继续for循环,i继续自增,并且继续放入定时事件2,3,当js代码片段执行完毕后,才继续依次执行定时事件1、2、3,此时i的值已经是3了.所以在控制台中我们看到的打印结果依次是:setTimeout:1,setTimeout:2,setTimeout:3,for循环:3,for循环:3,for循环:3.
其实这样看起来非常类似与传统多线程的异步编程,代码执行流并不会等setTimeout的函数执行完毕,再继续向下执行.但我们要了解的是,其实它们仍然是串行执行的,只不过是把setTimeout中设置的函数放到队列中延后执行,从而使js代码依然先执行,执行完毕后再依次执行事件队列中的函数.