ES7中的async 和 await

async 和 await

一個函數若是加上 async ,那麼該函數就會返回一個 Promise異步

async function test() {
  return "1"
}
console.log(test()) 
// -> Promise {<resolved>: "1"}

async 就是將函數返回值使用 Promise.resolve() 包裹了下,和 then 中處理返回值同樣,而且 await 只能配套 async 使用。async

async function test() {
  let value = await sleep()
}

async 和 await 能夠說是異步終極解決方案了,相比直接使用 Promise 來講,優點在於處理 then 的調用鏈,可以更清晰準確的寫出代碼,畢竟寫一大堆 then 也很噁心,而且也能優雅地解決回調地獄問題。函數

固然也存在一些缺點,由於 await 將異步代碼改形成了同步代碼,若是多個異步代碼沒有依賴性卻使用了 await 會致使性能上的下降。性能

async function test() {
  // 如下代碼沒有依賴性的話,徹底可使用 Promise.all 的方式
  // 若是有依賴性的話,其實就是解決回調地獄的例子了
  await fetch(url)
  await fetch(url1)
  await fetch(url2)
}

看一個使用 await 的例子:fetch

let a = 0
let b = async () => {
  a = a + await 10
  console.log('2', a)
}
b()
a++
console.log('1', a)

//先輸出  ‘1’, 1
//在輸出  ‘2’, 10
  • 首先函數 b 先執行,在執行到 await 10 以前變量 a 仍是 0,由於 await 內部實現了 generator ,generator 會保留堆棧中東西,因此這時候 a = 0 被保存了下來
  • 由於 await 是異步操做,後來的表達式不返回 Promise 的話,就會包裝成 Promise.reslove(返回值),而後會去執行函數外的同步代碼
  • 同步代碼 a++ 與打印 a 執行完畢後開始執行異步代碼,將保存下來的值拿出來使用,這時候 a = 0 + 10

上述解釋中提到了 await 內部實現了 generator,其實 await 就是 generator 加上 Promise 的語法糖,且內部實現了自動執行 generatorurl

代碼分析題

function wait() {
  return new Promise(resolve =>
    setTimeout(resolve,  1000)
  )
}

async function main() {
  console.time();
  const x = wait();
  const y = wait();
  const z = wait();
  await x;
  await y;
  await z;
  console.timeEnd();
}
main();

答案: 輸出耗時: 1秒多一點點。
緣由: 3個wait函數在賦值的時候就已經開始執行了。code

稍微改造一下就能夠獲得3 * 1000 ms以上的結果generator

function wait () {
  return new Promise(
    resolve => setTimeout(resolve,  1000)
  )
}

async function main () {
  console.time()
  const x = await wait()
  const y = await wait()
  const z = await wait()
  console.timeEnd()
}

main()
相關文章
相關標籤/搜索