IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Async/Await & Generator

    iwillwen发表于 2016-06-17 04:58:16
    love 0

    Async Function = A, Generator = G, A ≠ G, ∃A ∈ G, ∃G ∈ A

    Generator 我就不再介紹了,大家的用法看 Koa/co,真正意義看 https://zhuanlan.zhihu.com/p/20794401。

    我們來說說 async/await,自從 TJ 創造了 co 以後,一眾 JavaScript Diaosiloper 就瘋狂起來了:WOW,可以直接寫同步代碼了!

    後來 async/await 進入 ECMAScript 的 Draft,是的,到今天為止還沒有成為標準。就有人覺得,這不就是 co 的東西嗎?嗯,可以說 co 就是模仿 async/await 來創造的。這裡又要說到什麼是“協程”了,對不起,JavaScript 暫時並沒有資格說這個,所以我以 Go 語言來講講吧。

    package main
    
    import "fmt"
    
    func Add(x, y int, ch chan int) {
      z := x + y
      
      ch <- z
    }
    
    func main() {
      chs := make([]chan int, 10)
      for i := 0; i < 10; i++ {
        chs[i] := make(chan int)
        go Add(i, i + 1, chs[i])
      }
      
      for _, ch := range(chs) {
        val := <- ch // Waiting each coroutine to finish
        fmt.Println(val)
      }
    }
    

    Go 語言中利用 go 語句來將一個函數(Add)作為協程的運行內容創建一個協程,并通過 channel 特性來作為主線程與協程之間的通訊通道,因為 channel 的寫入和讀取具有原子性且同步的,所以如果協程內對 channel 的寫入並沒有完成,主線程中的讀取就會一直等待。

    這樣的好處是,可以將複雜的、耗時長的、甚至堵塞的代碼放在協程中運行,而主線程中只要在需要的時候把結果取出來便可以了。這就是協程的意義,OK。


    迴歸正題,async/await 跟 Generator 究竟有什麼差別?首先你要明白一點,兩者都可以完成類似於協程的任務。而如果非要說之間的差別,我可以這樣總結:

    Async Function is a common function, Generator Function is not.

    這話題一開始我就說了:

    Async Function = A, Generator = G, A ≠ G, ∃A ∈ G, ∃G ∈ A

    那麼在什麼情況下,他們之間存在包含關係呢?

    Async Function ∈ (Generator + co)

    是的,當 Generator 結合 co 時,Async Function 就變成了他們的子集,這就是 co 厲害的地方。

    當然,這是在 Node.js 中的情況。那麼在前端開發中,情況又會是怎麼樣的呢?


    我們知道前端開發需要響應用戶的操作事件,最基本就是點擊。假設有這樣一個場景,用戶在 input 中輸入一個 key,然後響應函數中需要從 MinDB 中讀取相應 key 的數據,并顯示在頁面上。

    <div id="app">
      <input type="text" v-model="key">
      <p>{{value}}</p>
      <button @click="query">Query</button>
    </div>
    
    <script>
      import Vue from 'vue'
      import min from 'min'
    
      new Vue({
        el: '#app',
    
        data: {
          key: '',
          value: ''
        },
    
        methods: {
          query() {
            min.get(this.key)
              .then(value => this.value)
          }
        }
      })
    </script>
    

    我們可以看到 MinDB 的數據讀取是異步的,而且使用的是 Promise,那麼自然就想到了可不可以通過技術手段來變成“同步代碼”呢?

    我們直接來看 async/await 吧。

    methods: {
      async query() {
        this.value = await min.get(this.key)
      }
    }
    

    好的,完事了。如果用 Generator 呢?

    methods: {
      query: function* () {
        this.value = yield min.get(this.key)
      }
    }
    

    嗯,看上去也不錯,但是運行之後便發現,沒報錯、也沒結果。為什麼?因為 Generator 並沒有運行起來。用 co 吧?

    methods: {
      query() {
        const self = this
        co(function* () {
           self.value = yield min.get(self.key)
        })
      }
    }
    

    ok,其餘自己想吧。



沪ICP备19023445号-2号
友情链接