Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redux、MobX 数据流的总结 #32

Open
riskers opened this issue Oct 20, 2017 · 0 comments
Open

Redux、MobX 数据流的总结 #32

riskers opened this issue Oct 20, 2017 · 0 comments
Labels
FE web 前端

Comments

@riskers
Copy link
Owner

riskers commented Oct 20, 2017


使用 redux-thunkredux-sagaredux-observableMobX制作同样的一个小项目:

data flow demo

这个项目调用github API查找 github 用户,点击头像之后还可以知道这个用户的 follower 和 following。简单来说,就是调用了三次 API(即三次异步请求)。


目录

本文不是教程,并不会手把手地教你如何使用他们,只是一个指引,一份示例,让你能够了解他们各自的特点,以便选择最适合自己的。


redux-thunk

code

redux-thunk我们在 Redux 中操作异步最简单的方法。配合 async/await,你可以像写同步代码一样进行异步操作。

示例

// action creators
const getUsers = username => {
  async dispatch => {
    dispatch({
      type: 'LOADING'
    })

    try{
      const response = await fetch(`https://example.com/`)
      let data = await response.json()

      dispatch({
        type: 'SUCCESS',
        payload: data
      })
    }catch(error) {
      dispatch({
        type: 'FAILURE',
        error: error
      })
    }
  }
}

redux-thunk flow

      dispatch                                       dispatch           update
VIEW ----------> function ----------> ACTION object ---------> REDUCER --------> STORE --------> STATE
|          (return async dispatch)                                ^
|                                                                 |
|                                                                 |
|                                                                 |
|       dispatch                                                  |
|---------------------> ACTION object -----------------------------

VIEW 会 dispatch 一个 ACTION object 或一个高阶函数(返回 async function):

  • 当 dispatch 一个 ACTION object 时,reducer 会更新数据
  • 当 dispatch 一个函数时,我们就可以在里面做各种异步操作(利用 await),然后 dispatch 一个 ACTION object,之后 reducer 更新数据

redux-saga

code

redux-saga 简化了 action creator,redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理。Sagas 可以被看作是在后台运行的进程,监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其他的 action 到 Store,甚至是调用其他的 Sagas。一旦出发 sagas 监听的 action,sagas 会通过一系列的effects dispatch (比如 put)一个 action。

示例

// action.js
export const searchUsers = (username, page) => {
  return {
    type: CONST.FETCH_GITHUB_SEARCH_USER,
    payload: {
      username,
      page
    }
  }
}
// App/sagas.js
function* fetchUsers(action) {
  let {
    username,
    page
  } = action.payload

  yield put({
    type: CONST.FETCH_GITHUB_SEARCH_USER_LOADING
  })

  yield call(delay, 2000)

  try {
    let response = yield call(fetch, `https://api.github.com/search/users?q=${username}&page=${page}`)
    let data = yield response.json()

    yield put({
      type: CONST.FETCH_GITHUB_SEARCH_USER_SUCCESS,
      payload: data
    })
  }catch(e) {
    yield put({
      type: CONST.FETCH_GITHUB_SEARCH_USER_FAILURE,
      error: "No This User"
    })
  }
}

export default function* () {
  yield takeLatest(CONST.FETCH_GITHUB_SEARCH_USER, fetchUsers)
}
// sagas/index.js
import AppSaga from 'containers/App/sagas'

export default function* rootSaga() {
  yield AppSaga()
}

redux-saga flow

      dispatch                  not match            update          update
VIEW ----------> ACTION object -----------> REDUCER --------> STORE --------> STATE
                       |                       ^
                       |                       |
                       |  match                |
                       |                       |
                       |  (data)               |
                       |                       |
                      \|     dispatch          |
                     SAGAS ------------>  ACTION object

VIEW dispatch 一个 ACTION object:

  • 这个 ACTION object 没有被 sagas 监听,则 reducer 会更新数据
  • 这个 ACTION object 被 sagas 监听,则走入 sagas 的流程,在 sagas 中 dispatch ACTION object,reducer 更新数据

redux-saga vs redux-thunk

  • 原理不同:Sagas 不同于 Thunks,Thunks 是在 action 被创建时调用,而 Sagas 会在应用启动时调用(但初始启动的 Sagas 可能会动态调用其他 Sagas),是常驻后台的(因为 generator)。

  • redux-saga 有cancel、takeLeast这些操作,这是 async 做不到的(这也是 generator 相对 async 的优势)

  • redux-saga 易测试,比如它可以无阻塞地调用一个 generator(fork)、中断一个 generator (cancel)。这些特性在业务逻辑复杂的场景下非常适用。测试代码详见这里

  • redux-saga 保持了 action 的原义,保持 action 的简洁,把所有有副作用的地方独立开来(这样action里会很干净)。这种特性让 redux-saga 在业务逻辑简单的场景下,也能保持代码清晰简洁。


redux-observable

code

你要先了解 rxjs ,然后再往下读。因为 redux-observable 就是让你能够在 Redux 中使用 rxjs。

为了方便理解 rxjs,我做了一个纯 js 版的项目 jsbin,之后能够我们再把它改成 react 版的。

redux-observable flow

      dispatch                  not match            update          update
VIEW ----------> ACTION object -----------> REDUCER --------> STORE --------> STATE
                       |                       ^
                       |                       |
                       |  match                |
                       |                       |
                       |  (data)               |
                       |                       |
                      \|     dispatch          |
                     EPICS ------------>  ACTION object

Epic 是 redux-observable 的核心,它是一个函数,接收 actions 流作为参数并且返回 actions 流: Actions 入, actions 出。返回的 actions 会通过 store.dispatch() 立刻被分发,所以 redux-observable 实际上会做 epic(action$, store).subscribe(store.dispatch)

redux-observable vs redux-saga

可以看到,redux-observable 和 redux-saga 的数据流是相似的。关于他们的异同,可以查看这两篇文章,不再赘述:


mobx

code

先看一个 demo,它包含了 @action @observable @observer @computed @inject 等重要概念。

MobX flow

                            modify                    update                    trigger
Events ----->  Actions  ------------->     State     --------> Computed values ---------->  Reactions
              (@action)                (@observable)             (@computed)               (@observer)
                 ^                                                                              |
                 |                                                                              |
                 |                                 (mobx-react)                                 |
                 |------------------------------------------------------------------------------|

MobX vs Redux

MobX vs Redux: Comparing the Opposing Paradigms 演讲已经介绍,不能看视频的看 MobX vs Redux: Comparing the Opposing Paradigms - React Conf 2017 纪要 也是可以的。



向我捐助 | 关于我 | 工作机会


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FE web 前端
Projects
None yet
Development

No branches or pull requests

1 participant