JavaScript运行机制
一、执行栈和任务队列
JS是单线程的,JS的任务还分为 同步任务 和 异步任务 。
- 所有同步任务都在主线程上执行,形成一个执行栈。
- 主线程之外,还有一个任务队列。当异步任务有了运行结果,就在任务队列中放置一个事件。
- 当执行栈中所有同步任务执行完毕,系统就会读取任务队列,那些有运行结果的异步任务结束等待进入执行栈,开始执行。
- 只要主线程空了,就会去读取任务队列。
执行栈和任务队列之间的事件循环机制会把任务队列里的任务不断推到执行栈中执行。
二、宏任务和微任务
异步任务又分为 宏任务 和 微任务 ,又各自有 宏任务队列 和 微任务队列。
- 宏任务:宿主环境提供的叫宏任务,script 、setTimeout、setInterval 、setImmediate 、I/O 、UI rendering、new关键字(new Promise等)。
- 微任务:语言标准提供的叫微任务,MutationObserver、Promise.then()或catch()、Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。
三、事件循环
Event loop 执行顺序:
- 一开始整个脚本作为一个宏任务执行;
- 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列;
- 当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完;
- 检查宏任务列表,有则依次执行;
- 执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空。
注意:在所有任务开始的时候,由于宏任务中包括了script,所以浏览器会先执行一个宏任务,在这个过程中你看到的延迟任务(例如setTimeout)将被放到下一轮宏任务中来执行。
四、问题
封装一个异步加载图片的方法
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function() {
console.log("一张图片加载完成");
resolve(img);
};
img.onerror = function() {
reject(new Error('Could not load image at' + url));
};
img.src = url;
});
五、参考
https://juejin.im/post/5e58c618e51d4526ed66b5cf#heading-52
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!