js是一门单线程的语言,不可能进行多线程编程,异步编程就是多线程编程一种模式,但是我们经常讲到js的异步编程,其实是伪异步,因为它是单线程的,也就是同步,只有前面的代码执行完才能执行下面的代码。所以要理解js中的异步理念,就需要了解js的运行核心--事件循环(Event loop)
为什么js会有异步呢
setTimeout(function(){
//5秒之后执行程序
},5000)
我们想象一下,在同步的执行上面的代码,需要等待5秒才能执行定时器中的程序,然后在往下执行,在这5秒的过程中,浏览器没有任何反应,出现了阻塞,在用户体验上很不好。所以异步的模式就出现,为了解决浏览器非阻塞的运行。
单线程如何做到异步
js的任务分为同步和异步两种,它们的处理方式也不同,同步任务是直接在主线程上排队执行,异步任务则会被放到事件队列中,若有多个异步任务则要在事件队列中排队等待,事件队列类似一个缓冲区,任务下一步会被移到调用栈,然后主线程执行调用栈的任务。
单线程是指js引擎中负责解析执行js代码的线程只有一个主线程,即每次只能做一件事,而我们知道一个ajax请求,主线程在等待它响应的同时是会去做其它事的,浏览器先在事件表注册ajax的回调函数,响应回来后回调函数被添加到任务队列中等待执行,不会造成线程阻塞,所以说js处理ajax请求的方式是异步的。
总而言之,检查调用栈是否为空,以及确定把哪个异步任务加入调用栈的这个过程就是事件循环,而js实现异步的核心就是事件循环。
一次事件循环的步骤包括:
- 主线程在执行代码的时候,遇到异步任务会将它添加到一个事件队列中(可以理解为一个数组),然后继续执行下面的代码,直到同步代码执行完,然后执行步骤2
- 检查事件队列是否为空,非空执行步骤3,为空则继续执行步骤2
- 取出事件队列中的第一个放到调用栈,然后主线程执行调用栈的任务,再执行步骤4
- 执行视图更新,然后回到步骤2
这就是事件循环
先看一段代码,理解一下:(面试题哦)
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顺序是什么?结合上面的步骤分析一下
最后的结果是:
start
end
promise1
pormise2
setTimeout
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。