js的执行机制

转载 js的执行机制

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事 多线程的话

JS为什么是单线程的

最初设计JS是用来在浏览器验证表单操控DOM元素的是一门脚本语言,如果js是多线程的,那么两个线程同时对一个DOM元素进行了相互冲突的操作,那么浏览器的解析器是无法执行的。

js为什么需要异步

如果js中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。 对于用户而言,阻塞就以为着“卡死”,这样就导致了很差的用户体验。比如在进行ajax请求的时候如果没有返回数据后面的代码就没办法执行

JS的事件循环(eventloop)是怎么运作的

“先执行同步操作异步操作排在事件队列里”这样的理解其实也没有任何问题但如果深入的话会引出很多其他概念,比如event table和event queue, 我们来看运行过程:

1.首先判断JS是同步还是异步,同步就进入主线程运行,异步就进入event table.
2.异步任务在event table中注册事件,当满足触发条件后,(触发条件可能是延时也可能是ajax回调),被推入event queue
3.同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主线程中。

宏任务 包含整个script代码块,setTimeout, setIntval

微任务 Promise , process.nextTick

那事件循环机制到底是怎么样的?

不同类型的任务会进入对应的event queue, 比如setTime和setIntval会进入相同(宏任务)的event queue, 而Promise和process.nextTick会进入相同(微任务)的event queue.

Promise与事件循环

Promise在初始化时,传入的函数是同步执行的,然后注册then回调。注册完之后,继续往下执行同步代码,在这之前,then的回调不会执行。同步代码块执行完毕后,才会在事件循环中检测是否有可用的promise回调,如果有,那么执行,如果没有,继续下一个事件循环。

new Promise(function (resolve) { 
    console.log('1')// 宏任务一
    resolve()
}).then(function () {
    console.log('3') // 宏任务一的微任务
})
setTimeout(function () { // 宏任务二
    console.log('4')
    setTimeout(function () { // 宏任务五
        console.log('7')
        new Promise(function (resolve) {
            console.log('8')
            resolve()
        }).then(function () {
            console.log('10')
            setTimeout(function () {  // 宏任务七
                console.log('12')
            })
        })
        console.log('9')
    })
})
setTimeout(function () { // 宏任务三
    console.log('5')
})
setTimeout(function () {  // 宏任务四
    console.log('6')
    setTimeout(function () { // 宏任务六
        console.log('11')
    })
})
console.log('2') // 宏任务一

初步总结:宏任务是一个栈按先入先执行的原则,微任务也是一个栈也是先入先执行。但是每个宏任务都对应会有一个微任务栈,宏任务在执行过程中会先执行同步代码再执行微任务栈。

posted @ 2021-02-23 21:23  BesePawn  阅读(99)  评论(0编辑  收藏  举报