天天看點

Async、Await 實作原理Async、Await 實作原理

Async、Await 實作原理

簡介

  • async 用于聲明一個函數是異步的
  • await 用于等待異步完成
  • await 隻能在 async 函數中使用
  • async 傳回一個 promise
  • await 後邊永遠跟的是一個 promise,如果是一個非 promise,則會自動轉換為 promise
  • Async、Await 是通過 Generator + Promise 實作

babel 轉碼

async function data1() {
  const aa = await new Promise(function(recolve) {
    setTimeout(function() {
      recolve()
    }, 3000)
  })
  console.log(1)
  console.log(2)
  await console.log(3)
  var bb = await (1 + 1)
}
           
// 通過 babel 轉碼之後的 ES5 代碼
var data1 = (function() {
  var _ref = _asyncToGenerator(
    /*#__PURE__*/ regeneratorRuntime.mark(function _callee() {
      var aa, bb
      return regeneratorRuntime.wrap(
        function _callee$(_context) {
          while (1) {
            switch ((_context.prev = _context.next)) {
              case 0:
                _context.next = 2
                return new Promise(function(recolve) {
                  setTimeout(function() {
                    recolve()
                  }, 3000)
                })
              case 2:
                aa = _context.sent
                console.log(1)
                console.log(2)
                _context.next = 7
                return console.log(3)
              case 7:
                _context.next = 9
                return 1 + 1
              case 9:
                bb = _context.sent
              case 10:
              case 'end':
                return _context.stop()
            }
          }
        },
        _callee,
        this
      )
    })
  )

  return function data1() {
    return _ref.apply(this, arguments)
  }
})()

function _asyncToGenerator(fn) {
  return function() {
    var gen = fn.apply(this, arguments)
    return new Promise(function(resolve, reject) {
      function step(key, arg) {
        try {
          var info = gen[key](arg)
          var value = info.value
        } catch (error) {
          reject(error)
          return
        }
        if (info.done) {
          resolve(value)
        } else {
          return Promise.resolve(value).then(
            function(value) {
              step('next', value)
            },
            function(err) {
              step('throw', err)
            }
          )
        }
      }
      return step('next')
    })
  }
}
           

通過上述代碼,babel 把我們原本的 async/await 代碼,轉換成了一個 Generator + Promise 的代碼。我們來看一下代碼:

  • 将 async/await 轉換為 _asyncToGenerator 包裝的 Generator
  • _asyncToGenerator 自動執行 next 方法
  • 第一次 _context.next = 0,執行對應的方法得到對應的 value

    var info = gen[key](arg); var value = info.value

    。這個 value 是一個 promise,是以當 value resolve 之後才會執行下一個 next 的,并将對應的值傳遞給 next 方法,這時候 _context.next = 2,在這裡将我們 resolve 的值傳遞給了 _context.sent,并在對應的 case 中指派給我定義的變量 aa
  • 當所有疊代器完成之後 resolve 最外層的 promise