javascript中的事件循环

javascript中的事件循环

一、什么是事件循环

javascript是一门单线程语言,单线程可以用事件循环的方法实现不阻塞。

javascript的任务可以分为两种:

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行。
  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等。

同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,回去任务队列读取对应的任务,推入主线程执行,上述过程的不断重复就是事件循环。

二、宏任务和微任务

javascript任务还可以分为宏任务和微任务。

1、微任务

一个需要异步执行的函数,执行时机是在主函数执行结束之后,当前宏任务结束之前。

常见的微任务有:

  • Promise.then
  • MutationObserver
  • Object.observe(已废弃:Proxy对象代替)
  • process.nextTick(Node.js)

2、宏任务

宏任务的事件粒度比较大,执行事件间隔是不能精确控制的,对一些高时效性的需求就不太符合。

常见的宏任务有:

  • script(可以理解微外层同步代码)
  • setTimeout/setInterval
  • UI rendering/UI 事件
  • postMessage、MessagChannel
  • setImmediate、I/O(Node.js)

宏任务和微任务的执行流程:

  • 执行一个宏任务,如果遇到微任务,将微任务放到微任务的事件队列中
  • 在当前宏任务执行完毕后,查看微任务的事件队列,将里面的微任务依次执行完
console.log(1)
setTimeout(()=>{
    console.log(2)
}, 0)
new Promise((resolve, reject)=>{
    console.log('new Promise')
    resolve()
}).then(()=>{
    console.log('then')
})
console.log(3)

首先是console.log(1),打印1;遇到setTimeout,这是新的宏任务,在后面执行;遇到new Promise,打印"new Promise";.then是微任务,放入微任务列表,后面执行;遇到console.log(3),打印3;本轮宏任务执行完毕,查看微任务列表,里面有.then,执行.then的回调,打印"then";微任务也执行完毕,去执行另一个宏任务–setTimeout,打印2。

三、async和await

async是异步的意思,用来声明异步的一个方法,await是用来等待异步方法执行。

1、async

async函数返回一个promise对象。

function f() {
    return Promise.resolve('TEST');
}

// asyncF is equivalent to f! 这两种等效
async function asyncF() {
    return 'TEST';
}

2、await

一般来说,await后面是一个Promise对象,返回该对象的结果,如果不是Promise对象,就直接返回对应的值。

async function f(){
    // 等同于
    // return 123
    return await 123
}
f().then(v => console.log(v)) // 123

不论await后面的是什么,await都会阻塞后面的代码。

async function fn1 (){
    console.log(1)
    await fn2()
    console.log(2) // 阻塞
}

async function fn2 (){
    console.log('fn2')
}

fn1()
console.log(3)

// 输出的顺序是 1 fn2 3 2

四、流程分析

async function async1() {
    console.log('async1 start') // 4
    await async2() // 5
    console.log('async1 end') // 7
}
async function async2() {
    console.log('async2') // 6
}
console.log('script start') // 1
setTimeout(function () {
    console.log('settimeout') // 2
})
async1() // 3
new Promise(function (resolve) {
    console.log('promise1') // 8
    resolve()
}).then(function () {
    console.log('promise2') // 9
})
console.log('script end') // 10

输出结果如下:
script start;async1 start;async2;promise1;script end;async1 end;promise2;settimeout

程序首先遇到 1 号,打印 script start ;然后遇到 2 号,是宏任务,先处理完当前宏任务和微任务再另外处理这个 2 号宏任务;遇到 3 号,执行 4 号,打印 async1 start ,遇到 5 号,执行 6 号,打印 async2 ,阻塞 7 号,将 7 号添加到微任务队列;遇到 8 号,执行,打印 promise1 ,遇到 9 号,将 9 号添加到微任务队列;遇到 10 号,执行,打印 script end。

至此,宏任务结束,依次执行微任务列表。

执行 7 号,打印 async1 end ,执行 9 号,打印 promise2 。

至此,微任务列表执行完毕,执行下一个宏任务。

执行 2 号,打印 settimeout。

全部执行完毕。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值