generator,promise 與 async/await 的關係

Promise

Promise 對象是一個代理對象(代理一個值),被代理的值在Promise對象建立時多是未知的。它容許你爲異步操做的成功和失敗分別綁定相應的處理方法(handlers)。 這讓異步方法能夠像同步方法那樣返回值,但並非當即返回最終執行結果,而是一個能表明將來出現的結果的promise對象
經常使用場景

若是遇到接口的調用參數依賴於上一個接口的返回值,咱們通常會這麼寫promise。es6

function getApi(params) {
  return new Promise((resolve) => {
    // 模擬ajax
    setTimeout(() => {
      resolve('api result: ' + params)
    }, 1000)
  })
}

getApi('start').then((res) => {
  getApi(res).then((res) => {
    getApi(res).then((res) => {
      console.log('finish', res)
    })
  })
})

promise的出現讓異步方法能夠像同步方法那樣返回值,可是並無解決回調地獄的問題,如上面的場景,接下來就該Generator出場了。ajax

Generator

es6新增了一種聲明方式,function *api

function* 這種聲明方式( function關鍵字後跟一個星號)會定義一個 生成器函數(generator function),它返回一個   Generator  對象。

生成器函數在執行時能暫停,後面又能從暫停處繼續執行。promise

調用一個生成器函數並不會立刻執行它裏面的語句,而是返回一個這個生成器的迭代器 ( iterator)對象。當這個迭代器的 next() 方法被首次(後續)調用時,其內的語句會執行到第一個(後續)出現yield的位置爲止,yield後緊跟迭代器要返回的值。或者若是用的是yield*(多了個星號),則表示將執行權移交給另外一個生成器函數(當前生成器暫停執行)。異步

next()方法返回一個對象,這個對象包含兩個屬性:value 和 done,value 屬性表示本次 yield 表達式的返回值,done 屬性爲布爾類型,表示生成器後續是否還有yield語句,即生成器函數是否已經執行完畢並返回。async

調用 next()方法時,若是傳入了參數,那麼這個參數會傳給上一條執行的 yield語句左邊的變量函數

運用生成器咱們就能夠這樣去改造上面的例子:
用生成器函數包裹咱們須要處理的語句,在yield後面跟咱們須要處理的promise函數,next()後會執行到下一個yield位置而後暫停當前生成器的執行,至於恢復的時機就是這個promise執行完成(fulfilled/rejected)的時候,這時再調用next(),繼續執行生成器接下來的語句,這裏咱們再實現一個自動運行生成器的方法。代理

function getApi(params) {
  return new Promise((resolve) => {
    // 模擬ajax
    setTimeout(() => {
      resolve('api result: ' + params)
    }, 1000)
  })
}

function* gen(stage0) {
  console.log(stage0)
  let stage1 = yield getApi('startParams')
  console.log('stage1', stage1)
  let stage2 = yield getApi(stage1)
  console.log('stage2', stage2)
  let stage3 = yield getApi(stage2)
  console.log('stage3', stage3)
  return 'all Done!!'
}

function run(generator, v) {
  let { value, done } = generator.next(v)
  if (!done) {
    value.then((res) => {
      run(generator, res)
    })
  } else {
    console.log(value)
  }
}

run(gen('start'))

async/await

es2017的新語法,對上面例子的改造就變成了code

function getApi(params) {
  return new Promise((resolve) => {
    // 模擬ajax
    setTimeout(() => {
      resolve('api result: ' + params)
    }, 1000)
  })
}

async function getAllApi() {
  let stage1 = await getApi('startParams')
  console.log('stage1', stage1)
  let stage2 = await getApi(stage1)
  console.log('stage2', stage2)
  let stage3 = await getApi(stage2)
  console.log('stage3', stage3)
  return 'all Done!!'
}

getAllApi()

因此說async/await就是generator + promise的語法糖,還自帶auto run的buff對象

相關文章
相關標籤/搜索