javaScript的事件循环机制

看不看得懂先来两张图:
浏览器运行机制:

上图中“js引擎线程,定时器触发器线程,事件出发线程”共同作用 的 js执行机制如下图

代码拿去跑跑就大致掌握了(实践出真知)

//层   也就是执行上下文
//同步输出 也就是进入执行栈js线程(注:宏任务以及所有的输出都属于同步输出)
// 在浏览器环境运行 请注释掉 process.nextTick 和 setImmediate


/**
 * JS所谓的“单线程”只是指主线程只有一个,并不是整个运行环境都是单线程
JS的异步靠底层的多线程实现
不同的异步API对应不同的实现线程
异步线程与主线程通讯靠的是Event Loop
异步线程完成任务后将其放入任务队列
主线程不断轮询任务队列,拿出任务执行
任务队列有宏任务队列和微任务队列的区别
微任务队列的优先级更高,所在执行上下文所有同步任务+微任务处理完后,才会处理下一个宏任务
Promise是微任务
Node.js的Event Loop跟浏览器的Event Loop不一样,他是分阶段的
setImmediate和setTimeout(fn, 0)哪个回调先执行,需要看他们本身在哪个阶段注册的,如果在定时器回调或者I/O回调里面,setImmediate肯定先执行。如果在最外层或者setImmediate回调里面,哪个先执行取决于当时机器状况。
process.nextTick不在Event Loop的任何阶段,他是一个特殊API,他会立即执行,然后才会继续执行Event Loop
 */

/**
 * macro-task大概包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task大概包括: process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)
 */
console.log('主任务 script层 入栈执行 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');

setTimeout(function () {
    console.log('宏任务 setTimeout1层 入栈执行 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
    console.log('宏任务 同步输出 setTimeout1(主函数)');
    new Promise(function (resolve) {
        console.log('同步输出 setTimeout1 promise1构造函数');
        resolve();
    }).then(function () {
        console.log('微任务@ setTimeout1 promise1.then')
        console.log("宏任务 setTimeout1层 以及本层所有微任务 执行完毕!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    })

    setTimeout(function () {
        console.log('宏任务 setTimeout11层 入栈执行 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
        console.log('宏任务 同步输出 setTimeout11(主函数)');
        new Promise(function (resolve) {
            console.log('同步输出 setTimeout11 promise11构造函数');
            resolve();
        }).then(function () {
            console.log('微任务@ setTimeout11 promise11.then')
        }).then(function () {
            console.log('我是微任务@promise11产生的微任务,也要执行完才可进行下一个宏任务哦')
            console.log("宏任务 setTimeout11层 以及本层所有微任务 执行完毕!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        })

    })
})

// setImmediate(function () {
//     console.log('immediate1');
//     process.nextTick(function () {
//         console.log('immediate1_nextTick');
//     })
//     new Promise(function (resolve) {
//         console.log('immediate1_promise');
//         resolve();
//     }).then(function () {
//         console.log('immediate1_then')
//     })
// })

setTimeout(function () {
    console.log('宏任务 setTimeout2层 入栈执行 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
    new Promise(function (resolve) {
        console.log('同步输出 setTimeout2 promise2构造函数');
        resolve();
    }).then(function () {
        console.log('微任务@ setTimeout2 promise2.then')
        console.log("宏任务 setTimeout2层 以及本层所有微任务 执行完毕!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    })

    setTimeout(function () {
        console.log('宏任务 setTimeout22层 入栈执行 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
        console.log('宏任务 同步输出 setTimeout22(主函数)');
        new Promise(function (resolve) {
            console.log('同步输出 setTimeout22 promise22构造函数');
            resolve();
        }).then(function () {
            console.log('微任务@ setTimeout22 promise22.then@')
        }).then(function () {
            console.log('我是微任务@promise22产生的微任务,也要执行完才可进行下一个宏任务哦')
            console.log("宏任务 setTimeout22层 以及本层所有微任务 执行完毕!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
        })

    })
})

// setImmediate(function () {
//     console.log('immediate2');
//     process.nextTick(function () {
//         console.log('immediate2_nextTick');
//     })
//     new Promise(function (resolve) {
//         console.log('immediate2_promise');
//         resolve();
//     }).then(function () {
//         console.log('immediate2_then')
//     })
// })


new Promise(function (resolve) {
    console.log('主任务 script层 同步输出 promise01构造函数');
    resolve();
}).then(function () {
    console.log('微任务@ promise01.then')
})

// process.nextTick(function () {
//     console.log('glob1_nextTick');
// })
//由此可见 nodejs中 process.nextTick 的异步优先级要比 promise.then 高

new Promise(function (resolve) {
    console.log('主任务 script层 同步输出 promise02构造函数');
    resolve();
}).then(function () {
    console.log('微任务@ promise02.then')

    console.log("主任务 script层 以及本层所有微任务 执行完毕!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
})

// process.nextTick(function () {
//     console.log('glob2_nextTick');
// })


 那么,根据打印的结果,我理解的 Promise 的执行逻辑是:

1. 按同步的运行顺序,执行 Promise 的构造函数

2. 将所有 Promise 构造函数后的第一个 then() 函数放入异步队列中(如果存在的话)

3.1 将所有 Promise 构造函数后的第二个 then() 函数放入异步队列中(如果存在的话)

setTimeout(() => {
  console.log(1)
}, 0)
new Promise((resolve, reject) => {
  console.log(2)
  resolve('p1')

  new Promise((resolve, reject) => {
    console.log(3)
    setTimeout(() => {
      resolve('setTimeout2')
      console.log(4)
    }, 0)
    resolve('p2')
  }).then(data => {
    console.log(data)
  })

  setTimeout(() => {
    resolve('setTimeout1')
    console.log(5)
  }, 0)
}).then(data => {
  console.log(data)
})
console.log(6)

//结果 : 2,3,6,p1,p2,1,4,5

参考文献地址:
setTimeout和setImmediate到底谁先执行,本文让你彻底理解Event Loop__蒋鹏飞的博客-CSDN博客
https://www.jianshu.com/p/12b9f73c5a4f
这一次,彻底弄懂 JavaScript 执行机制 - 掘金
在此感谢大佬们的分享,受教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值