[Web] mobx 異步操做

轉載自:https://www.jianshu.com/p/66dd328726d7git

 

異步actiongithub

action只能影響正在運行的函數,而沒法影響當前函數調用的異步操做 。 action 包裝/裝飾器只會對當前運行的函數做出反應,而不會對當前運行函數所調用的函數(不包含在當前函數以內)做出反應
也就是說promise的then或async語句,而且在回調函數中某些狀態改變了,這些回調函數也應該包裝在action中。
(1)第一種方案,使用action關鍵字來包裝promises的回調函數。
// 第一種寫法
class Store {

@observable githubProjects = []
@observable state = "pending" // "pending" / "done" / "error"

@action
fetchProjects() {
    this.githubProjects = []
    this.state = "pending"
    fetchGithubProjectsSomehow().then(
        // 內聯建立的動做
        action("fetchSuccess", projects => {
            const filteredProjects = somePreprocessing(projects)
            this.githubProjects = filteredProjects
            this.state = "done"
        }),
        // 內聯建立的動做
        action("fetchError", error => {
            this.state = "error"
        })
    )
 }
}

// 第二種寫法promise

 class Store {
     @observable githubProjects = []
     @observable state = "pending" // "pending" / "done" / "error"

     @action
     fetchProjects() {
         this.githubProjects = []
         this.state = "pending"
         fetchGithubProjectsSomehow().then(
             projects => {
                 const filteredProjects = somePreprocessing(projects)
                 // 將修改放入一個異步動做中
                 runInAction(() => {
                     this.githubProjects = filteredProjects
                     this.state = "done"
                  })
             },
             error => {
                 runInAction(() => {
                     this.state = "error"
                 })
             }
         )
     }
 }

第二種方案,用async function來處理業務,那麼咱們能夠使用runInAction這個API來解決以前的問題 。異步

import {observable, action, useStrict, runInAction} from 'mobx';
useStrict(true);

class Store {
  @observable name = '';
  @action load = async () => {
    const data = await getData();
    // await以後,修改狀態須要動做
    runInAction(() => {
      this.name = data.name;
    });
  }
}
  1. flows
    然而,更好的方式是使用 flow 的內置概念。它們使用生成器。一開始可能看起來很不適應,但它的工做原理與 async / await 是同樣的。只是使用 function * 來代替 async,使用 yield 代替 await 。 使用 flow 的優勢是它在語法上基本與 async / await 是相同的 (只是關鍵字不一樣),而且不須要手動用 @action 來包裝異步代碼,這樣代碼更簡潔。

flow 只能做爲函數使用,不能做爲裝飾器使用。 flow 能夠很好的與 MobX 開發者工具集成,因此很容易追蹤 async 函數的過程。async

mobx.configure({ enforceActions: true })

class Store {
    @observable githubProjects = []
    @observable state = "pending"

    fetchProjects = flow(function * () { // <- 注意*號,這是生成器函數!
        this.githubProjects = []
        this.state = "pending"
        try {
            const projects = yield fetchGithubProjectsSomehow() // 用 yield 代替 await
            const filteredProjects = somePreprocessing(projects)
            // 異步代碼塊會被自動包裝成動做並修改狀態
            this.state = "done"
            this.githubProjects = filteredProjects
        } catch (error) {
            this.state = "error"
        }
    })
}
相關文章
相關標籤/搜索