We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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-thunk、 redux-saga、 redux-observable、 MobX制作同样的一个小项目:
这个项目调用github API查找 github 用户,点击头像之后还可以知道这个用户的 follower 和 following。简单来说,就是调用了三次 API(即三次异步请求)。
本文不是教程,并不会手把手地教你如何使用他们,只是一个指引,一份示例,让你能够了解他们各自的特点,以便选择最适合自己的。
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 }) } } }
dispatch dispatch update VIEW ----------> function ----------> ACTION object ---------> REDUCER --------> STORE --------> STATE | (return async dispatch) ^ | | | | | | | dispatch | |---------------------> ACTION object -----------------------------
VIEW 会 dispatch 一个 ACTION object 或一个高阶函数(返回 async function):
redux-saga 简化了 action creator,redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理。Sagas 可以被看作是在后台运行的进程,监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其他的 action 到 Store,甚至是调用其他的 Sagas。一旦出发 sagas 监听的 action,sagas 会通过一系列的effects dispatch (比如 put)一个 action。
action creator
put
// 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() }
dispatch not match update update VIEW ----------> ACTION object -----------> REDUCER --------> STORE --------> STATE | ^ | | | match | | | | (data) | | | \| dispatch | SAGAS ------------> ACTION object
VIEW dispatch 一个 ACTION object:
原理不同: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 在业务逻辑简单的场景下,也能保持代码清晰简洁。
你要先了解 rxjs ,然后再往下读。因为 redux-observable 就是让你能够在 Redux 中使用 rxjs。
为了方便理解 rxjs,我做了一个纯 js 版的项目 jsbin,之后能够我们再把它改成 react 版的。
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)。
store.dispatch()
epic(action$, store).subscribe(store.dispatch)
可以看到,redux-observable 和 redux-saga 的数据流是相似的。关于他们的异同,可以查看这两篇文章,不再赘述:
先看一个 demo,它包含了 @action @observable @observer @computed @inject 等重要概念。
@action
@observable
@observer
@computed
@inject
modify update trigger Events -----> Actions -------------> State --------> Computed values ----------> Reactions (@action) (@observable) (@computed) (@observer) ^ | | | | (mobx-react) | |------------------------------------------------------------------------------|
MobX vs Redux: Comparing the Opposing Paradigms 演讲已经介绍,不能看视频的看 MobX vs Redux: Comparing the Opposing Paradigms - React Conf 2017 纪要 也是可以的。
向我捐助 | 关于我 | 工作机会
The text was updated successfully, but these errors were encountered:
No branches or pull requests
使用 redux-thunk、 redux-saga、 redux-observable、 MobX制作同样的一个小项目:
目录
redux-thunk
code
redux-thunk我们在 Redux 中操作异步最简单的方法。配合 async/await,你可以像写同步代码一样进行异步操作。
示例
redux-thunk flow
VIEW 会 dispatch 一个 ACTION object 或一个高阶函数(返回 async function):
redux-saga
code
redux-saga 简化了
action creator
,redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理。Sagas 可以被看作是在后台运行的进程,监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其他的 action 到 Store,甚至是调用其他的 Sagas。一旦出发 sagas 监听的 action,sagas 会通过一系列的effects dispatch (比如put
)一个 action。示例
redux-saga flow
VIEW dispatch 一个 ACTION object:
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
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
MobX vs Redux
MobX vs Redux: Comparing the Opposing Paradigms 演讲已经介绍,不能看视频的看 MobX vs Redux: Comparing the Opposing Paradigms - React Conf 2017 纪要 也是可以的。
The text was updated successfully, but these errors were encountered: