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


猜你喜欢

转载自www.cnblogs.com/0616--ataozhijia/p/11727935.html