JavaScript执行机制

12次阅读

共计 2307 个字符,预计需要花费 6 分钟才能阅读完成。

1. 单线程

javascript 是一门单线程语言

2.javascript 事件循环

  • 同步任务
  • 异步任务


除了广义的同步任务和异步任务,我们对任务有更精细的定义:

  • macro-task(宏任务):包括整体代码 script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick(类似 node.js 版的 ”setTimeout”)



事件循环的顺序,决定 js 代码的执行顺序。进入整体代码 (宏任务) 后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

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')
    })
})

结果:整段代码,共进行了三次事件循环,完整的输出为 1,7,6,8,2,4,3,5,9,11,10,12。
(请注意,node 环境下的事件监听依赖 libuv 与前端环境不完全相同,输出顺序可能会有误差)

3.Node 与浏览器 EventLoop 的差异

浏览器和 Node 环境下,microtask 任务队列的执行时机不同

  • Node 端,microtask 在事件循环的各个阶段之间执行
  • 浏览器端,microtask 在事件循环的 macrotask 执行完之后执行

例子:

setTimeout(()=>{console.log('timer1')
    Promise.resolve().then(function() {console.log('promise1')
    })
}, 0)
setTimeout(()=>{console.log('timer2')
    Promise.resolve().then(function() {console.log('promise2')
    })
}, 0)

浏览器端运行结果:timer1=>promise1=>timer2=>promise2

Node 端运行结果分两种情况:

  • 如果是 node11 版本一旦执行一个阶段里的一个宏任务 (setTimeout,setInterval 和 setImmediate) 就立刻执行微任务队列,这就跟浏览器端运行一致,最后的结果为 timer1=>promise1=>timer2=>promise2
  • 如果是 node10 及其之前版本:要看第一个定时器执行完,第二个定时器是否在完成队列中。

    如果是第二个定时器还未在完成队列中,最后的结果为 timer1=>promise1=>timer2=>promise2
    如果是第二个定时器已经在完成队列中,则最后的结果为 timer1=>timer2=>promise1=>promise2

4. 使用 Promise 实现串行

  • 递归执行:

简单来说就是在 then 方法里面递归传递下一次异步方法:then(next())

  • 循环调用:

这种办法比较取巧,直接利用 Promise.resolve()。通过循环赋值,得到最终的结果。

5. 为何 try 里面放 return,finally 还会执行

6. 如何在保证页面运行流畅的情况下处理海量数据

大致的执行流程是:

  1. 用 ajax 获取到需要处理的数据,共 13 万条
  2. 将数组分组,每组 500 条,一共 260 组
  3. 循环这 260 组数据,分别处理每一组数据,利用 setTimeout 函数开启一个新的执行线程(异步),防止主线程因渲染大量数据导致阻塞。

总结:

(1)js 的异步

我们从最开头就说 javascript 是一门单线程语言,不管是什么新框架新语法糖实现的所谓异步,其实都是用同步的方法去模拟的,牢牢把握住单线程这点非常重要。

(2)事件循环 Event Loop

事件循环是 js 实现异步的一种方法,也是 js 的执行机制。

(3)javascript 的执行和运行

执行和运行有很大的区别,javascript 在不同的环境下,比如 node,浏览器,Ringo 等等,执行方式是不同的。而运行大多指 javascript 解析引擎,是统一的。

(4)setImmediate

微任务和宏任务还有很多种类,比如 setImmediate 等等,执行都是有共同点的,有兴趣的同学可以自行了解。

(5)最后的最后

javascript 是一门单线程语言
Event Loop 是 javascript 的执行机制

部分内容转自:
1).https://juejin.im/post/59e85e…
2).https://juejin.im/post/5b30b0…
3).https://zhuanlan.zhihu.com/p/…

正文完
 0