Redux store 仅支持同步数据流。
使用 redux-thunk、redux-saga、redux-promise 等中间件可以帮助在 Redux 应用中实现异步性。
1、redux-thunk是作为redux的 middleware 存在的,用法和普通 middleware 的用法是一样的,注册 middleware 的代码如下:
import thunkMiddleware from 'redux-thunk'
const store = createStore(reducer, applyMiddleware(thunkMiddleware))
redux-thunk主要的功能就是可以让我们dispatch一个函数,而不只是普通的 Object
原理:核心代码其实只有两行,就是判断每个经过它的action:如果是function类型,就调用这个function(并传入 dispatch 和 getState 及 extraArgument 为参数),而不是任由让它到达 reducer,因为 reducer 是个纯函数,Redux 规定到达 reducer 的 action 必须是一个 plain object 类型。
使用场景:
// 用于发起登录请求,并处理请求结果
// 接受参数用户名,并返回一个函数(参数为dispatch)
const login = (userName) => (dispatch) => {
dispatch({ type: 'loginStart' })
request.post('/api/login', { data: userName }, () => {
dispatch({ type: 'loginSuccess', payload: userName })
})
}
store.dispatch(login('Lucy'))
示例代码中,我们定义了 login 函数做 API 请求,在请求发出前我们可能需要展示一个全局的 loading bar,在请求结束后我们又需要将请求结果存储到 redux store 中。这都需要用到 redux 的 dispatch。
2、redux-saga
基于 es6 Generator语法,将异步操作逻辑存放在一个地方进行集中处理,通过 yield 关键字,可以让函数的执行流挂起。
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const store = createStore(appReducer, applyMiddleware(...middlewares));
sagaMiddleware.run(rootSaga);
监听被dispatch的actions,当接收到action或者知道其被触发时,调用worker saga执行任务
原理:redux-saga相当于在Redux原有数据流中多了一层,通过对Action进行监听,从而捕获到监听的Action,然后可以派生一个新的任务对state进行维护(这个看项目本身的需求),通过更改的state驱动View的变更
import { fork, all, call, put, takeEvery, takeLatest } from 'redux-saga/effects'
fork 创建一个新的进程或者线程,并发发送请求
call: 发送 api 请求 异步执行
all:all 跟 fork 一样,同时并发多个 action,没有顺序
put: put 发送对应的 dispatch,触发对应的 action
take: 是用来监听action,返回的是监听到的action对象 暂停Generator
匹配的action被发起时,恢复执行。take结合fork,可以实现takeEvery和takeLatest的效果
takeEvery: 监听对应的 action 每一次 dispatch 都会触发
takeLatest: 监听对应的 action 只会触发最后一次 dispatch, 例如:点击一个新增的按钮,2s 后触发新增动作,在2s内不断点击按钮,这时候,只有最后一次点击是有效的
cancel: 指示 middleware 取消之前的 fork 任务,cancel 是一个无阻塞 Effect。race 竞速执行多个任务
3.redux-promise
使用redux-promise中间件,允许action是一个promise
原理:如果action是一个promise,则会等待promise完成,将完成的结果作为action触发,如果action不是一个promise,则判断其payload是否是一个promise,如果是,等待promise完成,然后将得到的结果作为payload的值触发。
网友评论