es基础之异步

异步

setTimeout 会放到代码结束之后执行。
异步不会阻塞后面程序执行

异步和单线程

1
2
3
var a = true
setTimeout(function(){a=false},100)
while(true){console.log)('x')}

因为js是单线程的,进入while之后会死循环,没有线程去跑定时器。

异步的场景

setTimeout setInterval 和 网络请求

promise

##async/await

要合理使用 async,要小心不必要的promise依赖

定时器

setTimeout(0) 不是马上执行,是单线程的js忙完了其他逻辑才运行,是异步的

可以考虑 requestAnimationFrame 这个函数自带节流 16.6ms

promise

单独开一篇吧。

浏览器中的 eventLoop

js遇到异步函数,会放到task里,等到当前执行队列空,开始执行task。

本质上,异步还是同步演变。

task分为两种:

  • 微观任务micro task 称为 job
  • 宏观任务 marco task 称为 task
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
console.log('script start') // 1

async function async1() {
await async2()// 去下一个 让出来
console.log('async1 end')//7
}
async function async2() {
console.log('async2 end')//2
}
async1()

setTimeout(function() {
console.log('setTimeout')//9
}, 0)

new Promise(resolve => {
console.log('Promise') //3
resolve()
})
.then(function() {
console.log('promise1')//5
})
.then(function() {
console.log('promise2')//6
})
console.log('script end') //4

观察这段代码。1-4 5-9
1-2牢记promise await是回调。
2-3-4 顺序执行 promise
然后继续执行 promise的回调 5-6
7 promise任务结束,继续回调
9 setTimeout

总结:

  • 先执行同步代码,这是宏观任务。
  • 同步代码结束,当前执行队列空,看异步代码
  • 执行微观任务
  • 渲染页面
  • 执行完微观任务,回到宏观任务执行setTimeout等

所以,promise和 setTimeout 比,promise是微观任务先执行

微观任务 process.nextTick promise MutationObserver
宏观任务 script setTimeout setInterval setImmediate I/O UI Rendering

node中的 event loop

和浏览器完全不同
node分为六个阶段,反复执行

timers – pending callbacks – idle,prepare – poll – check – close callbacks

timer

执行 setTimeout setInterval

I/O

处理上一轮循环中少数未执行的I/O 回调

poll

  • 回调timer阶段
  • 执行 io 回调

慢慢看吧。

请我喝杯咖啡吧~