es基础之异步

异步 #

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

异步和单线程 #

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

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

异步的场景 #

setTimeout setInterval 和 网络请求

promise

##async/await

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

定时器 #

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

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

promise #

单独开一篇吧。

浏览器中的 eventloop #

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

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

task分为两种:

  • 微观任务micro task 称为 job
  • 宏观任务 marco task 称为 task
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 回调

慢慢看吧。