有学有练才叫学习:学而不思则罔,思而不学则殆:学而不习,纸上谈兵,习而不进,画地为牢!

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

javascript cat 5个月前 (04-25) 44次浏览 已收录 0个评论 扫描二维码

一、关于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中回调的异步微任务
定时器中的定时器(宏任务)
*/
喜欢 (0)
cat
关于作者:
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址