JavaScript是单线程的,也就是说,同一个时刻,JavaScript只能执行一个工作,其余工作只能期待。
1.为什么JavaScript是单线程的?
js是运行于浏览器的脚本语言,因其常常波及操作dom,如果是多线程的,也就意味着,同一个时刻,可能执行多个工作。
试想,如果一个线程批改dom,另一个线程删除dom,那么浏览器就不晓得该先执行哪个操作。
所以js执行的时候会依照一个工作一个工作来执行。
2.为什么工作要分为同步工作和异步工作?
试想一下,如果js的工作都是同步的,那么遇到定时器、网络申请等这类型须要延时执行的工作会产生什么?
页面可能会瘫痪,须要暂停下来期待这些须要很长时间能力执行结束的代码
所以,又引入了异步工作。
- 同步工作:同步工作
不须要期待
可立刻看到执行后果,比方console - 异步工作:异步工作
须要期待
肯定的时候能力看到后果,比方setTimeout、网络申请
异步工作,又能够细分为宏工作和微工作。上面列举目前学过的宏工作和微工作。
工作(代码) | 宏/微 工作 | 环境 |
---|---|---|
script | 宏工作 | 浏览器 |
事件 | 宏工作 | 浏览器 |
网络申请(Ajax) | 宏工作 | 浏览器 |
setTimeout() 定时器 | 宏工作 | 浏览器 / Node |
fs.readFile() 读取文件 | 宏工作 | Node |
Promise.then() | 微工作 | 浏览器 / Node |
他们的执行过程是怎么的呢?
比方去银行排队办业务,每个人的业务就相当于是一个宏工作;
比方一个人,办的业务有存钱、买纪念币、买理财产品、办信用卡,这些就叫做微工作。
执行程序:
概念
1.宏工作:以后调用栈中执行的代码成为宏工作。(主代码快,定时器等等)。
2.微工作: 以后(此次事件循环中)宏工作执行完,在下一个宏工作开始之前须要执行的工作,能够了解为回调事件。(promise.then,proness.nextTick等等)。
3.宏工作中的事件放在callback queue中,由事件触发线程保护;微工作的事件放在微工作队列中,由js引擎线程保护。
事件循环(Event Loop)
事件循环就是一个在 "JavaScript 引擎期待工作","执行工作"和"进入休眠状态期待更多任务"这几个状态之间转换的有限循环。
引擎的个别算法:
当有工作时:
- 从最先进入的工作开始执行。
- 休眠直到呈现工作,而后转到第 1 步。
常见面试题
1.
console.log(1)setTimeout(function() { // 定时器是宏工作 console.log(2)}, 0)const p = new Promise((resolve, reject) => { resolve(1000) // 微工作})p.then(data => { console.log(data)})console.log(3)// 运行后果: 1, 3, 1000, 2
面试题剖析:
先剖析有几次事件循环? 有两次事件循环:第一次先运行script标签外面的内容,在执行栈中运行后,先打印的是 1, 3;在运行过程中遇到的微工作是要加到微工作队列外面期待,当执行栈中的工作运行完后,在执行微工作,即打印 1000,此时第一次循环完结,第二次循环在执行栈中运行定时器,则最总输入后果是:1, 3, 1000, 2
2.
console.log(1)setTimeout(function() { console.log(2) new Promise(function(resolve) { console.log(3) resolve() }).then(function() { console.log(4) })})new Promise(function(resolve) { console.log(5) resolve()}).then(function() { console.log(6)})setTimeout(function() { console.log(7) new Promise(function(resolve) { console.log(8) resolve() }).then(function() { console.log(9) })})console.log(10)// 运行后果 : 1 5 10 6 2 3 4 7 8 9
3.
console.log(1) setTimeout(function() { console.log(2) }, 0) const p = new Promise((resolve, reject) => { console.log(3) resolve(1000) // 标记为胜利 console.log(4) }) p.then(data => { console.log(data) }) console.log(5) // 运行后果: 1 3 4 5 1000 2
4.
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 p2 p1 1 4 5
能够做一下题,增强了解