javascript 执行机制(同步、异步、微任务、宏任务)

一、关于javascript
JS是一门单线程语言,这意味着所有的任务都需要排队,前一个任务结束才会执行后一个任务如果前一个任务耗时很长,后一个任务就不得不一直等着。
这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

 

二、同步任务和异步任务
单线程导致的问题就是后面的任务等待前面任务完成,如果前面任务很耗时(比如读取网络数据),后面任务不得不一直等待。
为了解决这个问题,利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JS 脚本实现“多个线程”(JS是单线程这一核心仍未改变。所以一切"多线程"都是用单线程模拟出来的),但是子线程完全受主线程控制。于是,JS 中出现了同步任务和异步任务。

1.同步任务
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。
比如有五个顾客来到了你的饭店,同步的做法是:先给第一个顾客点菜,然后做菜,结束后再给第二个人…以此类推。

2.异步任务
异步任务:不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。
比如有五个顾客来到了你的饭店,异步的做法是:先给每一个顾客点菜,点完之后给他们一个牌子并把对应的菜单放到后厨然后让他们等待,之后后厨根据他们的菜单开始做菜。

 

三、微任务和宏任务
异步任务又分为微任务和宏任务。

1.微任务
包括Promise,process.nextTick

Promise(async/await) => Promise并不是完全的同步,在promise中是同步任务,执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到微任务队列。当主栈完成后,才会再去调用resolve/reject方法执行

process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找)

MutationObserver (创建并返回一个新的 MutationObserver 它会在指定的DOM发生变化时被调用。)

2.宏任务
包括整体代码script,setTimeout,setInterval

定时器

事件绑定

ajax

回调函数

Node中fs可以进行异步的I/O操作

 

四、执行顺序
执行顺序总结:先做同步任务,在做异步任务,异步任务又分为微任务和宏任务,先做微任务在做宏任务。
同步任务 => 异步任务( 微任务 => 宏任务 )
需要知道的是JS是单线程的,他的异步编程仅仅是根据某些机制来管控任务的执行顺序,所以并不存在同时执行两个任务这一说法。

 

五、示例

console.log("同步任务1");
​
function workFun(mac) {
    console.log("同步任务2");
    if (mac) {
        console.log(mac);
    }
    return new Promise((resolve, reject) => {
        console.log("Promise中的同步任务");
        resolve("Promise中回调的异步微任务")
    })
}
setTimeout(() => {
    console.log("异步任务中的宏任务");
    setTimeout(() => {
        console.log("定时器中的定时器(宏任务)");
​
    }, 0)
    workFun("定时器传递任务").then(res => {
        console.log('定时器中的:', res);
    })
}, 0)
workFun().then(res => {
    console.log(res);
})
console.log("同步任务3")

/*
** 同步任务1 
同步任务2
Promise中的同步任务
同步任务3
Promise中回调的异步微任务

异步任务中的宏任务
同步任务2
定时器传递任务
Promise中的同步任务
定时器中的: Promise中回调的异步微任务
定时器中的定时器(宏任务)
*/

 

posted @ 2022-08-18 10:54  小刺猬的大宝贝  阅读(573)  评论(0编辑  收藏  举报