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
能够做一下题,增强了解
发表回复