JavaScript 事件循环

js是一门单线程的语言,不可能进行多线程编程,异步编程就是多线程编程一种模式,可是咱们常常讲到js的异步编程,实际上是伪异步,由于它是单线程的,也就是同步,只有前面的代码执行完才能执行下面的代码。因此要理解js中的异步理念,就须要了解js的运行核心--事件循环(Event loop)html

为何js会有异步呢

setTimeout(function(){
    //5秒以后执行程序
    
},5000)

咱们想象一下,在同步的执行上面的代码,须要等待5秒才能执行定时器中的程序,而后在往下执行,在这5秒的过程当中,浏览器没有任何反应,出现了阻塞,在用户体验上很很差。因此异步的模式就出现,为了解决浏览器非阻塞的运行。html5

单线程如何作到异步

js的任务分为同步异步两种,它们的处理方式也不一样,同步任务是直接在主线程上排队执行,异步任务则会被放到事件队列中,如有多个异步任务则要在事件队列中排队等待,事件队列相似一个缓冲区,任务下一步会被移到调用栈,而后主线程执行调用栈的任务。web

单线程是指js引擎中负责解析执行js代码的线程只有一个主线程,即每次只能作一件事,而咱们知道一个ajax请求,主线程在等待它响应的同时是会去作其它事的,浏览器先在事件表注册ajax的回调函数,响应回来后回调函数被添加到任务队列中等待执行,不会形成线程阻塞,因此说js处理ajax请求的方式是异步的。面试

总而言之,检查调用栈是否为空,以及肯定把哪一个异步任务加入调用栈的这个过程就是事件循环,而js实现异步的核心就是事件循环。ajax

一次事件循环的步骤包括:编程

  1. 主线程在执行代码的时候,遇到异步任务会将它添加到一个事件队列中(能够理解为一个数组),而后继续执行下面的代码,直到同步代码执行完,而后执行步骤2
  2. 检查事件队列是否为空,非空执行步骤3,为空则继续执行步骤2
  3. 取出事件队列中的第一个放到调用栈,而后主线程执行调用栈的任务,再执行步骤4
  4. 执行视图更新,而后回到步骤2

这就是事件循环api

先看一段代码,理解一下:(面试题哦)数组

console.log('start')

setTimeout(function() {
  console.log('setTimeout')
}, 0)

Promise.resolve().then(function() {
  console.log('promise1')
}).then(function() {
  console.log('promise2')
})

console.log('end')

打印台输出的log顺序是什么?结合上面的步骤分析一下promise

Event Loop

最后的结果是:浏览器

start
end
promise1
pormise2
setTimeout

参考资料

Event Loop