[Web] mobx 異步操作


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

 

異步action

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"
        })
    )
 }
}

// 第二種寫法

 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 函數的過程。

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"
        }
    })
}

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM