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
。這個 value 是一個 promise,是以當 value resolve 之後才會執行下一個 next 的,并将對應的值傳遞給 next 方法,這時候 _context.next = 2,在這裡将我們 resolve 的值傳遞給了 _context.sent,并在對應的 case 中指派給我定義的變量 aavar info = gen[key](arg); var value = info.value
- 當所有疊代器完成之後 resolve 最外層的 promise