前言:以前用redux处理异步状态都使用redux-thunk那个库。也一直听说redux-saga是个和redux-thunk能够实现类似功能的库,而且redux-saga的处理方法更加高压和方便。这几天阅读了下文档写些小结。
yield* takeEvery('PRODUCTS_REQUESTED', fetchProducts)
takeEvery('\*', function * xx(){/\** ***/})
表示匹配所有的actiontips: effects纯文本Javascript对象
- call
- call()
调用给定函数。注意的是,如果call调用fetch,在默认的fetch状态下返回的是Promise实例,但是由于是call调用,返回的是文本信息,可以直接调用
- put
- put({type: 'INCREMENT'})
发起一个action到store
- take 第二个参数表示对应匹配的action所要执行的函数。第一个参数如果是数组的话,表示可以并发监听action
- 可以更好的控制状态流
- 如下一个函数控制登陆和登出
//一个简单的登陆逻辑实现
//这个是会被阻塞的
function* loginFlow() {
while(true) {
const = {} = yield take('LOGIN')//左侧可以获取到这个action的一些信息
// ... perform the login logic
yield take('LOGOUT')
// ... perform the logout logic
}
}
import { take, call, put } from 'redux-saga/effects'
import Api from '...'
function* authorize(user, password) {
try {
const token = yield call(Api.authorize, user, password)
yield put({type: 'LOGIN_SUCCESS', token})
return token
} catch(error) {
yield put({type: 'LOGIN_ERROR', error})
}
}
function* loginFlow() {
while(true) {
const {user, password} = yield take('LOGIN_REQUEST')
const token = yield call(authorize, user, password)
if(token) {
yield call(Api.storeItem({token}))
yield take('LOGOUT')
yield call(Api.clearItem('token'))
}
}
}
function* authorize(user, password) {
try {
const token = yield call(Api.authorize, user, password)
yield put({type: 'LOGIN_SUCCESS', token})
return token
} catch(error) {
if(!isCancelError(error))
yield put({type: 'LOGIN_ERROR', error})
}
function* loginFlow() {
while(true) {
const {user, password} = yield take('LOGIN_REQUEST');//监听登录请求
const task = yield fork(authorize, user, password)//收到登陆请求后,发起认真。因为是fork所以是不阻塞下面的take['LOGOUT','LOGIN_ERROR']的
const action = yield take(['LOGOUT', 'LOGIN_ERROR'])
if(action.type === 'LOGOUT')
yield cancel(task) //取消之前的fork事务。因为可能登录请求未成功我们就发起了登出的事件。取消fork事务的时候,会在authorize内抛出一个错误
yield call(Api.clearItem('token'))//清空本地的token
}
}
function* backgroundTask() {
while(true) { ... }
}
function* watchStartBackgroundTask() {
while(true) {
yield take('START_BACKGROUND_TASK')
yield race({
task: call(backgroundTask),
cancel: take('CANCEL_TASK')//例如接受到CANCEL_TASK 的action的时候,backgroundTask函数内就会抛出异常
})
}
}
使用redux-saga来处理一些复杂的流程的时候似乎比较不错