持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
一、js的单线程模式
我们都知道js是单线程的,即只有一个线程,一次执行一个任务,队列中后面的任务需要要等前面的任务执行完后才能开始执行。
所以js程序的执行是同步的(同步是指按顺序执行,并非同时执行),这样避免了两个任务同时对DOM进行操作的时候产生冲突。而浏览器是多线程的。
这种模式的弊端就是,当遇到非常耗时的任务,会导致浏览器假死(无响应)。
于是,异步的出现就是解决了单线程运行阻塞的问题。
举个栗子: 打电话给餐厅,问是否可以预订座位。
同步:工作人员说:“请稍等,正在查询...”,不挂断电话,等待查询完成后告诉我们结果(可能1分钟之后,也可能1天之后)
异步:工作人员说:“查询后给您回电”,挂断电话,不立即返回结果,有结果后再通知我们
二、异步
在js中任务分为两类:
- 同步任务(synchronous)
- 异步任务(asynchronous)
当开始执行js程序的时候,同步的代码会放在可主线程中,而遇到异步的代码,就会被挂起并加⼊到任务队列中。当主线程中的任务全部执行完毕,就会开始读取队列,将队列中的异步任务放入主线程中。(栈stack的特性是后进先出,队列queue的特性是先进先出)
下图就是一个完整的运行过程,消息队列是用于存放异步任务:
常见的异步回调:
- setTimeout
- setInterval
- Ajax
setTimeout(function(){},1000);//隔1秒后执行函数,仅执行一次
setInterval(function(){},1000);//每隔1秒执行一次函数
三、事件循环(EventLoop)
事件循环是一种循环机制,它的核心就是回调函数
异步任务分为:宏任务与微任务,在下篇中有详细介绍:juejin.cn/post/710492…
宏任务与微任务
-
栈中执行的任务都是宏任务
<script>整体代码、setTimeout、setInterval、I/O、UI交互事件等都属于宏任务 -
宏任务执行结束后立即执行的任务就是微任务
- Promise的.then、.catch、.finally属于微任务(Promise属于同步任务)
- process.nextTick等属于微任务
-
执行顺序:当前宏任务->当前宏任务中的所有微任务->下一个宏任务
举个栗子:
b、d部分属于同步任务,c属于微任务,a是宏任务
setTimeout(function() {console.log('a');},1000)
new Promise(function(resolve) {
console.log('b');
resolve()
}).then(function() {
console.log('c');
})
console.log('d');
输出结果是:b d c a