1.概述
edux-saga是一个用于管理redux应用异步操作的中间件,redux-saga通过创建sagas将所有异步操作逻辑收集在一个地方集中处理,可以用来代替redux-thunk中间件。
2.流程
- ui组件触发
action
创建函数 action
创建函数返回一个action
action
被传入redux中间件(被 saga等中间件处理) ,产生新的action
,传入reducer
reducer
把数据传给ui组件显示mapStateToProps
- ui组件显示
3.使用
store.js
import {createStore,combineReducers, applyMiddleware} from 'redux';
import userNameReducer from '../username/reducer.js';
import createSagaMiddleware from 'redux-saga'; // 引入redux-saga中的createSagaMiddleware函数
import rootSaga from './saga.js'; // 引入saga.js
const sagaMiddleware = createSagaMiddleware() // 执行
const reducerAll = {
userNameReducer: userNameReducer
}
export const store = createStore(
combineReducers({...reducerAll}), // 合并reducer
window.devToolsExtension ? window.devToolsExtension() : undefined, // dev-tools
applyMiddleware(sagaMiddleware) // 中间件,加载sagaMiddleware
)
sagaMiddleware.run(rootSaga) // 执行rootSaga
// username.js
import React from 'react';
export default class User extends React.Component {
componentDidMount() {
console.log(this.props)
}
go = () => {
this.props.getAges(3) // 发起action,传入参数
}
render() {
return (
<div>
这是username组件
<div>
{
this.props.username.userNameReducer.username
}
</div>
<br/>
<div onClick={this.go}>
点击获取提交age
</div>
</div>
)
}
}
// action.js
import { actionTypes } from './constant.js';
export function getAges(age) {
console.log(age,'age') // 3
return {
type: actionTypes.GET_AGE,
payload: age
}
}
// saga.js
import { actionTypes } from '../username/constant.js';
import {call, put, takeEvery} from 'redux-saga/effects'; // 引入相关函数
function* goAge(action){ // 参数是action创建函数返回的action
console.log(action)
const p = function() {
return fetch(`http://image.baidu.com/channel/listjson?rn=${action.payload}...`,{
method: 'GET'
})
.then(res => res.json())
.then(res => {
console.log(res)
return res
})
}
const res = yield call(p) // 执行p函数,返回值赋值给res
yield put({ // dispatch一个action到reducer, payload是请求返回的数据
type: actionTypes.GET_AGE_SUCCESS,
payload: res
})
}
function* rootSaga() { // 在store.js中,执行了 sagaMiddleware.run(rootSaga)
yield takeEvery(actionTypes.GET_AGE, goAge) // 如果有对应type的action触发,就执行goAge()函数
}
export default rootSaga; // 导出rootSaga,被store.js文件import
4.名词解释
-
Effect
一个effect就是一个纯文本javascript对象,包含一些将被saga middleware执行的指令。
-
Task
一个 task 就像是一个在后台运行的进程,在基于redux-saga的应用程序中,可以同时运行多个task
-
阻塞调用 和 非组塞调用
阻塞调用:阻塞调用的意思是: saga 会在 yield 了 effect 后会等待其执行结果返回,结果返回后才恢复执行 generator 中的下一个指令
非阻塞调用:非阻塞调用的意思是: saga 会在 yield effect 之后立即恢复执行 -
watcher 和 worker
watcher:监听发起的action 并在每次接收到action时 fork 一个 work
worker: 处理action,并结束它 -
Effect
5.常用API
-
5.1 createSagaMiddleware(…sagas)
createSagaMiddleware
的作用是创建一个redux中间件,并将sagas
与Redux store
建立链接- 参数是一个数组,里面是
generator
函数列表
-
5.2 middleware.run(saga, …args)
- 动态执行 saga。用于
applyMiddleware
阶段之后执行 Sagas。这个方法返回一个
Task 描述对象。 saga
: Function: 一个 Generator 函数args
: Array: 提供给 saga 的参数 (除了 Store 的 getState 方法)
- 动态执行 saga。用于
-
5.4 take(pattern)
- 创建一条 Effect 描述信息,指示 middleware 等待 Store 上指定的 action。
- 发起一个 action 到 store
- 匹配规则
-1) pattern为空
或者*
,将会匹配所有发起的action
-2) pattern是一个函数,action
会在pattern(action)
返回为true
时被匹配
-3) pattern是一个字符串,action
会在action.type === pattern
时被匹配
-4 ) pattern是一个数组,每一项引用以上规则进行匹配
-
5.5 call(fn, …args)
- 和原生
call()
函数差不多
- 和原生
-
5.6 select(selector, …args)
- 得到 Store 中的 state 中的数据
-
5.7 race(effects)
effects
: Object : 一个{label: effect, ...}
形式的字典对象
-
5.8 cancel(task)
- 创建一条 Effect 描述信息,指示
middleware
取消之前的fork
任务。
- 创建一条 Effect 描述信息,指示
-
5.9 join(task)
- 等待
fork
任务返回结果(task
对象)
- 等待
-
5.10 fork(fn, …args)
- 无阻塞的执行fn,执行fn时,不会暂停Generator
yield fork(fn ...args)
的结果是一个Task
对象