首先咱们看一下如下代码打印结果javascript
console.log(1); setTimeout(function() { console.log(2); },100) setTimeout(function() { console.log(3); },50) console.log(4);
打印结果是 一、四、三、2,你可能以为理所应当,那咱们再看下下面这个例子java
console.log(1); setTimeout(function() { console.log(2); },0) console.log(3);
此次的结果又会是什么呢?浏览器
一、三、2,不是一、二、3。到这里你可能会有疑惑了,明明定时器设置的时间为0,并且浏览器解析js是按照从上到下执行的,应该是一、二、3才对啊?异步
到这里咱们要提一下浏览器的线程问题。函数
与js相关的浏览器线程有三个(注意:js解析是单线程) - js代码执行线程( 主线程 ) - UI渲染线程 - 事件循环线程spa
其中js代码执行线程与UI渲染线程二者是互斥的,也就是说js代码执行线程运行的时候,UI渲染线程会中止工做,这样作也是为了防止js中的DOM操做会致使两线程冲突;而事件循环线程比较特殊,接下来会根据setTimerout的执行过程进行讲解其做用。线程
回到上面的第一道题目code
console.log(1); setTimeout(function() { console.log(2); },100) setTimeout(function() { console.log(3); },50) console.log(4);
执行过程:blog
js主线程运行,遇到console.log(1),直接运行,在控制台输出结果;队列
主线程继续运行,而后遇到第一个setTimeout,接着setTimeout中的回调函数会被放入到一个事件队列中(这里的事件队里能够想象成一个备忘录,里面记录的全是一些须要作而未作的事);
遇到第二个setTimeout,其中的回调函数依然被加入到事件队列中;
执行console.log(4),到这里主线程的任务所有执行完毕,除了setTimeout里面的回调函数;
这个时候,咱们还未说明的事件循环线程开始工做,它会去循环遍历事件队列(也就是咱们的备忘录),若是事件队列中有回调函数,它就会将事件队列中的回调函数从新交给主线程;
主线程收到回调函数,而后开始执行函数体。(这里要注意,由于两个setTimeout自己有执行时间,因此在这里的时候就会根据时间的长短按顺序执行啦。)
setInterval原理与之相同,不做另说。
总的来讲,setTimeout与setInterval的执行会等到主线程的全部任务所有执行后,才会再执行其中的回调函数,因此在使用它们的时候也要注意,特别是在主线程中有特别耗时的任务的时候,两种定时器会被不可预测的延后。
讲到这里,你们有没有想到什么呢?
恩,就是异步,setTimeout的执行有没有一点异步的感受呢?但又由于它必须是等到主线程所有执行完才会执行,因此能够称之为伪异步。
说到异步,咱们还会想到AJAX,都说AJAX是异步,可是它异步的原理想必还不清楚的你应该有点兴趣了解的。
异步:简单说就是在处理某一件事的时候还能够去作别的事,好比:你在银行取号后等待取钱,在等待的过程当中你还能够玩手机,和别人聊天等等,这个过程就是异步的。
总的说来,AJAX的请求不会干扰到主线程任务的执行,它有本身专供的线程来处理其任务,就像是浏览器的亲儿子~~~