JavaScript执行机制 — 事件循环

举报
爱吃肉的茂茂 发表于 2021/07/16 16:26:11 2021/07/16
【摘要】 事件循环简单介绍及示例

单线程

总所周知,JavaScript是一门单线程语言!

JS作为一种脚本语言,多被用于浏览器中进行Web开发,它的主要用途是通过操作DOMBOM等达到与用户进行交互的目的。这也就意味着它只能是单线程的,以此来避免多个线程对同一DOM元素进行冲突的操作。

虽然H5出了一个新特性WebWorker为JS创造多线程环境,但多用来计算密集型或高延迟的任务,让主线程流程不被阻塞。但WebWorker也有诸多限制,同源限制,DOM限制,通信限制,脚本限制及文件限制等,这里不多做叙述。

异步

如果JS在执行一行代码时,解析时间过长,例如:大量数据的循环遍历等,那么后面的代码将会被阻塞,暂时无法执行,对用户而言,页面就卡住了,没办法进行迅速有效的交互,此时就需要JS进行异步操作!

异步的实现,也就是JS的执行机制 — 事件循环(event loop)

事件循环

因为JS是单线程的,所以所有的任务都是需要排队的,这里将JS的任务分为两种:

  • 同步任务(synchronous):在主线程上排队执行的任务
  • 异步任务(asynchronous):不进入主线程,而是进入“任务队列”(task queue)的任务

任务队列也是事件队形,运行机制大致如下:

  • 同步任务在主线程上执行,形成一个执行栈(先进先出)
  • 当执行栈执行完所有同步任务后,主线程将从“任务队列”中读取事件,执行异步任务

异步任务又细分为:

  • 宏观任务:宏观即指宿主,也是就是写代码的人发起的任务(整体代码script,setTimeout,setInterval)
  • 微观任务:微观即指JS,由JS引擎发起的任务(Promise.then是Promise的回调函数,process.nextTick)

完整的事件循环:

  1. 第一轮循环将整体JS当作一个宏任务来运行,主线程判断任务类型,同步任务逐步执行,当遇到异步任务将其推入事件队列(宏任务推入宏任务队列,微任务推入当前宏任务的微任务队列)
  2. 主线程执行完一轮轮同步(宏)任务后,依次执行当前的所有微任务
  3. 执行完当前所有任务,结束第一轮循环,开始第二轮循环
  4. 执行同步(宏)任务,将微任务推入当前的宏任务的微任务队列
  5. 开始循环往复

示例1:

console.log('1')
setTimeout(function() {
    console.log('2')
    process.nextTick(function() {
        console.log('3')
    })
    new Promise(function(resolve) {
        console.log('4')
        resolve()
    }).then(function() {
        console.log('5')
    })
})

process.nextTick(function() {
    console.log('6')
})

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

setTimeout(function() {
    console.log('9')
    process.nextTick(function() {
        console.log('10')
    })
    new Promise(function(resolve) {
        console.log('11')
        resolve()
    }).then(function() {
        console.log('12')
    })
})

示例2:

async function testSometing() {
    console.log("执行testSometing");
    return "testSometing";
}

async function testAsync() {
    console.log("执行testAsync");
    return Promise.resolve("hello async");
}

async function test() {
    console.log("test start...");
    const v1 = await testSometing();
    console.log(v1);
    const v2 = await testAsync();
    console.log(v2);
    console.log(v1, v2);
}

test();

var promise = new Promise((resolve) => {
    console.log("promise start..");
    resolve("promise");
});
promise.then((val) => console.log(val));
setTimeout(()=>{console.log("setTime1")},3000);
console.log("test end...")
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。