宏任务 微任务 消息队列 事件循环

1.执行栈:

showName()
console.log(myname)
var myname = 'JS执行栈'
function showName() {
    console.log('函数showName被执行');
}

执行结果:

函数showName被执行

undefined

原因:

JS代码执行过程为:

编译阶段:生成执行上下文和可执行代码。

具体以这段代码为例:

showName()
console.log(myname)
var myname = 'JS执行栈'
function showName() {
    console.log('函数showName被执行');
}

//变量环境

var myname =  undefined;
function showName() {
    console.log('函数showName被执行');
}   

//可执行代码

showName();
console.log(myname);
myname = 'JS执行栈'

任务循环:以单线程的JavaScript为基础,在管理多任务的同时,兼顾代码执行的效率和事件响应的的实时性。

2.JavaScript任务循环基本模型
JavaScript单线程:
在上面的执行代码中,我们把所有任务代码按照顺序写进主线程里,等线程执行时,这些任务会按照顺序在线程中依次被执行;等所有任务执行完成之后,线程会自动退出。可以参考下图来直观地理解下其执行过程:

线程内部事件处理:

要想在线程运行过程中,能接收并执行新的任务,就需要采用事件循环机制。

线程间事件处理:

消息队列:一种数据结构,可以存放要执行的任务。它符合队列“先进先出”的特点,也就是说要添加任务的话,添加到队列的尾部;要取出任务的话,从队列头部去取。

添加一个消息队列;

IO 线程中产生的新任务添加进消息队列尾部;

渲染主线程会循环地从消息队列头部中读取任务,执行任务。

进程间事件处理:
渲染进程专门有一个 IO 线程用来接收其他进程传进来的消息,接收到消息之后,会将这些消息组装成任务发送给渲染主线程,后续的步骤就和前面讲解的“处理其他线程发送的任务”一样了。

3.任务分类:
任务分类目的:平衡当前任务的执行效率和监控的实时性。

实时性:
如果将当前产生的任务都放在任务队列的尾部,则又会影响一些优先级较高的任务执行。即:当触发一个任务后,过了可能会过很长时间才执行,前面不太紧急的任务占用了大量时间。

效率:
如果当前任务一产生新的任务就立即执行,那么如果产生的新任务执行时间较长,就会阻塞当前任务的执行。

宏任务:
消息队列中的任务称为宏任务,每个宏任务中都包含(维护)了一个微任务队列,在执行宏任务的过程中,如果 DOM 有变化,那么就会将该变化添加到微任务列表中,(如果产生了优先级较高的任务,就将该任务以微任务的方式添加到微任务队列)这样就不会影响到宏任务的继续执行,因此也就解决了执行效率的问题。

微任务:
等宏任务中的主要功能都直接完成之后,这时候,渲染引擎并不着急去执行下一个宏任务,而是执行当前宏任务中的微任务,因为 DOM 变化的事件都保存在这些微任务队列中(我们在执行宏任务的同步代码时,将优先级较高的任务添加到了微任务队列中),这样也就解决了实时性问题。

宏任务包含(产生宏任务的方式):
渲染事件(如解析 DOM、计算布局、绘制);

用户交互事件(如鼠标点击、滚动页面、放大缩小等);

JavaScript 脚本执行事件;网络请求完成、文件读写完成事件。

主代码块

setTimeout

setInterval

setImmediate ()-Node

requestAnimationFrame ()-浏览器

微任务包含(产生微任务的方式):

process.nextTick ()-Node

Promise.then()

catch

finally

Object.observe

MutationObserver

4.执行时机:
宏任务:在任务队列中排队执行。

微任务:在当前任务的同步代码执行完之后,任务结束前(下一个宏任务开始执行前)。

5.示例:

function fun1() {
    setTimeout(() => {
        console.log('timeout-1')
    }, 0)
    console.log('test-1')
}
fun1()


function fun2() {
    Promise.resolve().then(() => {
        console.log('promise-1')
    })
    console.log('test-2')
}

fun2()


function fun3() {
    setTimeout(() => {
        console.log('timeout-3')
    })
    Promise.resolve().then(() => {
        console.log('promise-3')
    })
    console.log('test-3')
}
fun3()


let p4 = new Promise((resolve, rejest) => {
    console.log('创建promise-4')
})

function fun4() {
    p4.then(() => {
        console.log('p4-then')
    })
    console.log('test-4')
}

fun4()


let p5 = new Promise((resolve, rejest) => {
    console.log('创建promise-5')
    setTimeout(() => {
        resolve()
    },3000)
})

function fun5() {
    p5.then(() => {
        console.log('p5-then')
    })
    console.log('test-5')
}
fun5()


console.log('1');

setTimeout(function() {
    console.log('2');
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})

new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值