js 运行机制(含异步机制、同步任务、异步任务、宏任务、微任务、Event Loop)

简介: js 运行机制(含异步机制、同步任务、异步任务、宏任务、微任务、Event Loop)

js 的同步任务和异步任务

js代码可以分为两种任务:

  • 同步任务(synchronous)—— 在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
  • 异步任务(asynchronous)—— 不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

异步任务又分为宏任务与微任务:

  • 宏任务(macrotask )
事件/函数 浏览器环境 Node.js环境
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame
  • 微任务(microtask )
事件/函数 浏览器环境 Node.js环境
process.nextTick
MutationObserver
Promise.then catch finally

js在浏览器中的运行机制

从上到下依次解释执行所有代码

  • 遇到同步任务时,在主线程立刻执行该任务。
    此时主线程上有一个执行栈(execution context stack),所有同步代码会按顺序执行。
  • 遇到异步任务时,异步任务会进入到Event Table,当异步任务有结果后,将相对应的回调函数进行注册,放入事件队列(Event Queue);(异步的宏任务有结果后,会放入宏任务事件队列;异步的微任务有结果后,会放入微任务事件队列;)

(1)主线程从上到下依次执行所有同步任务

(2)主线程读取微任务事件队列,若存在微任务,则依次执行所有微任务

  • 微任务中同步任务会依次立刻执行
  • 微任务中微任务会依次添加到微任务事件队列末尾,待下一次读取微任务事件队列时执行
  • 微任务中宏任务会依次添加到宏任务事件队列末尾,待下一次读取宏任务事件队列时执行

(3)主线程读取宏任务事件队列,若存在宏任务,则依次执行所有宏任务

  • 宏任务中同步任务会依次立刻执行
  • 宏任务中微任务会依次添加到微任务事件队列末尾,待下一次读取微任务事件队列时执行
  • 宏任务中宏任务会依次添加到宏任务事件队列末尾,待下一次读取宏任务事件队列时执行

(4)依次重复第2步和第3步,直到清空微任务事件队列和宏任务事件队列

Event Loop(事件循环):主线程循环不断从"任务事件队列"中读取事件的运行机制称为Event Loop,这个过程是循环不断的,所以整个的这种运行机制

Event Loop 并不是在 ECMAScript 标准中定义的,而是在 HTML 标准中定义的

测试js在浏览器中运行机制的代码

console.log('0号同步任务1');
new Promise(function (resolve) {
    console.log('0号同步任务2');
    resolve();
}).then(function () {
    // 1号微任务
    setTimeout(function () {
        console.log('1号微任务中的宏任务1');
    })
    console.log('1号微任务中的同步任务1')
    new Promise(function (resolve) {
        console.log('1号微任务中的同步任务2');
        resolve();
    }).then(function () {
        // 1.1号微任务
        console.log('1.1号微任务中的同步任务1')
        setTimeout(function () {
            console.log('1.1号微任务中的宏任务1');
        })
        console.log('1.1号微任务中的同步任务2')
        setTimeout(function () {
            console.log('1.1号微任务中的宏任务2');
        })
    })
    console.log('1号微任务中的同步任务3')
    setTimeout(function () {
        console.log('1号微任务中的宏任务2');
    })
})
setTimeout(function () {
    console.log('0号宏任务中的同步任务1');
    new Promise(function (resolve) {
        console.log('0号宏任务中的同步任务2');
        resolve();
    }).then(function () {
        // 0号宏任务中的1号微任务
        setTimeout(function () {
            console.log('0号宏任务中的1号微任务中的宏任务1');
        })
        console.log('0号宏任务中的1号微任务中的同步任务1')
        new Promise(function (resolve) {
            console.log('0号宏任务中的1号微任务中的同步任务2');
            resolve();
        }).then(function () {
            //  0号宏任务中的1.1号微任务
            console.log('0号宏任务中的1.1号微任务中的同步任务1')
            setTimeout(function () {
                console.log('0号宏任务中的1.1号微任务中的宏任务1');
            })
        })
        console.log('0号宏任务中的1号微任务中的同步任务3')
    })
})
new Promise(function (resolve) {
    console.log('0号同步任务3');
    resolve();
}).then(function () {
    // 2号微任务
    setTimeout(function () {
        console.log('2号微任务中的宏任务1');
    })
    console.log('2号微任务中的同步任务1')
    new Promise(function (resolve) {
        console.log('2号微任务中的同步任务2');
        resolve();
    }).then(function () {
        // 2.1号微任务
        console.log('2.1号微任务中的同步任务1')
        setTimeout(function () {
            console.log('2.1号微任务中的宏任务1');
        })
    })
    console.log('2号微任务中的同步任务3')
})
console.log('0号同步任务4');

运行结果

0号同步任务1
0号同步任务2
0号同步任务3
0号同步任务4
1号微任务中的同步任务1
1号微任务中的同步任务2
1号微任务中的同步任务3
2号微任务中的同步任务1
2号微任务中的同步任务2
2号微任务中的同步任务3
1.1号微任务中的同步任务1
1.1号微任务中的同步任务2
2.1号微任务中的同步任务1
0号宏任务中的同步任务1
0号宏任务中的同步任务2
0号宏任务中的1号微任务中的同步任务1
0号宏任务中的1号微任务中的同步任务2
0号宏任务中的1号微任务中的同步任务3
0号宏任务中的1.1号微任务中的同步任务1
1号微任务中的宏任务1
1号微任务中的宏任务2
2号微任务中的宏任务1
1.1号微任务中的宏任务1
1.1号微任务中的宏任务2
2.1号微任务中的宏任务1
0号宏任务中的1号微任务中的宏任务1
0号宏任务中的1.1号微任务中的宏任务1


js在node.js中的运行机制

(1)V8引擎解析JavaScript脚本。

(2)解析后的代码,调用Node API。

(3)libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。

(4)V8引擎再将结果返回给用户。

Node.js还提供了另外两个与"任务队列"有关的方法:process.nextTick和setImmediate。

  • process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。【多个process.nextTick语句总是在当前"执行栈"一次执行完】
  • setImmediate方法则是在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行。【多个setImmediate可能则需要多次loop才能执行完。】

由于process.nextTick指定的回调函数是在本次"事件循环"触发,而setImmediate指定的是在下次"事件循环"触发,所以很显然,前者总是比后者发生得早,而且执行效率也高(因为不用检查"任务队列")。

目录
相关文章
|
4天前
|
JavaScript 前端开发
Node.js 中实现多任务下载的并发控制策略
Node.js 中实现多任务下载的并发控制策略
|
5月前
|
JavaScript 前端开发 API
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务
该文章详细讲解了队列数据结构在前端开发中的应用,并深入探讨了JavaScript的事件循环机制,区分了宏任务和微任务的执行顺序及其对前端性能的影响。
|
3月前
|
JSON 前端开发 JavaScript
在 JavaScript 中,如何使用 Promise 处理异步操作?
通过以上方式,可以使用Promise来有效地处理各种异步操作,使异步代码更加清晰、易读和易于维护,避免了回调地狱的问题,提高了代码的质量和可维护性。
|
4月前
|
前端开发 JavaScript 开发者
JS 异步解决方案的发展历程以及优缺点
本文介绍了JS异步解决方案的发展历程,从回调函数到Promise,再到Async/Await,每种方案的优缺点及应用场景,帮助开发者更好地理解和选择合适的异步处理方式。
|
4月前
|
移动开发 JavaScript 前端开发
【JavaScript】JS执行机制--同步与异步
【JavaScript】JS执行机制--同步与异步
39 1
|
4月前
|
JavaScript 前端开发 调度
在JavaScript中异步任务里的微任务和宏任务的特点和生命周期
在JavaScript中异步任务里的微任务和宏任务的特点和生命周期
58 0
|
3月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
49 1
JavaScript中的原型 保姆级文章一文搞懂
|
7月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
138 2
|
3月前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
33 0
|
7月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
195 4

热门文章

最新文章

  • 1
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    23
  • 2
    Node.js 中实现多任务下载的并发控制策略
    32
  • 3
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    25
  • 4
    【JavaScript】深入理解 let、var 和 const
    48
  • 5
    【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
    44
  • 6
    【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
    53
  • 7
    【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
    55
  • 8
    如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
    71
  • 9
    【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
    55
  • 10
    JavaWeb JavaScript ③ JS的流程控制和函数
    62