异步编程联系到的宏任务微任务

504 阅读2分钟

相关概念

  • 同步和异步的概念(相对两个参与者)

  •    同步:阻塞的
    
  •    异步:不阻塞的
    
  • js的执行环境:单线程+事件队列(任务队列)

  • 什么样的任务会进入任务队列?

    • 定时函数(时间到了)
    • Ajax回调函数(后端有数据返回)
    • 事件处理函数(特定事件被触发)
  • 任务队列中的任务何时执行?

    • 主线程空闲
    • 任务队列中的任务满足特定的触发条件

`

// 如下的打印是否一定发生在2秒后?不一定
// 当2秒到的时候,此时主线程可能正在忙
setTimeout(() => {
  console.log('hello')
}, 2000)

`

  • 宏任务和微任务

  • 宏任务:进入任务队列的任务

  • 微任务:不进入浏览器的任务队列,但是会进入另一个队列(内存中自定义队列)

    • 微任务队列是通过js代码实现的一种数据结构(可以理解为类似数组的的结构),该任务队列中任务触发的时机:主线程结束后,宏任务执行之前

    • 主线程 ---> 微任务 ---> 宏任务

    • 何种代码属于微任务?Promise

image-20210822112654388.png

代码实现

  • 回调函数
  • Promise
  • Async/await

. 异步的结果无法通过返回值获取

<script>
  function queryData() {
    let ret = null
    setTimeout(() => {
      let data = {
        uname: 'lisi',
        age: 12
      }
      // 这里return的是queryData函数的返回值吗?不是
      // 是该回调函数的返回值
      // return data
      ret = data
    }, 2000)
    return ret
  }
​
  // 需求:2秒后获取函数内部异步的结果数据
  let ret = queryData()
  console.log(ret)
</script>
  1. 异步结果需要通过回调函数的方式才可以得到
<script>
  function queryData(callback) {
    setTimeout(() => {
      let data = {
        uname: 'lisi',
        age: 12
      }
      // 调用回调函数(2秒后才会调用回调函数)
      callback(data)
    }, 2000)
  }
  // 结论:异步的结果必须用回调函数才可以获取到
  queryData((ret) => {
    console.log(ret)
  })
</script>
  1. 如果有多个异步任务,并且要保证异步任务执行的顺序,需要如何处理?

需求:有3个异步任务a/b/c,分别延时1/2/3秒返回异步的数据,要求得到数据的顺序:c-->a-->b

  • 要想实现上述任务,需要进行回调函数的嵌套,如果嵌套层次太多,就会出现回调地狱问题
  1. 由于回调地狱代码可读性较差,所以就诞生了一种新的技术:Promise

Promise是回调函数一种语法糖,一种改进的写法,但是并没有在本质上发生变化(依然是为了得到异步结果)

  1. Promise中依然有回调,也不是最好的方案,所以ES7引入了新的方案:async函数