持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
一、什么是Redux-saga
Redux-saga是一个用于管理Redux异步操作的中间件,在saga中,全局监听器和接收器使用Generator函数和saga自身的一些辅助函数实现对整个流程的管控。其本质是一个可以自执行的Generator函数,它对异步操作进行集中管控处理,方便我们对于Redux异步流程的管控 流程:
二、Redux-saga是如何运行的
Redux-saga监听view视图层dispatch的action,判断是否是saga监测的action,如果是,将会执行异步任务,并利用Generato对异步任务同步化,最后dispatch新操作,从而改变redux中的state。
- 监听用户发出的Action,并与自身监听Action做比对
- 如果用户发出的Action是自己当前监听的Action,然后执行副作用(派发一个新的任务)。
- reducer接收新任务,返回新数据并更新state。
Redux-saga流程图
三、实例操作
1.安装redux-saga
npm i redux-saga
2.新建文件
在src下新建redux-saga文件夹
(1) Main.js中视图层dispatch action
import React, { Component } from 'react'
import store from './redux/store'
export default class Main extends Component {
render() {
return (
<div>
<button onClick={()=>{
store.dispatch({
type:'get-list'
})
}}>
redux-sage
</button>
</div>
)
}
}
(2) reducer.js中存放我们对应action操作及数据
function reducer(preState={
list:{}
},action={}){
console.log(action)
switch(action.type){
case 'change-list':
let newState={...preState}
newState.list=action.payload
return newState
default:
return preState
}
}
export default reducer
(3) saga.js中执行监听操作
注意是从 redux-saga/effects引入take、fork、put、call方法(API使用请参考本文第四模块),该文件Generator使用较多,不了解同学建议回顾学习ES6该部分知识。
定义监听函数watchSaga,take方法用于监听组件发来的action,检测是否与自己匹配,fork函数同步处理异步函数。
在generator函数getList中,call函数用于执行并发送异步请求,其参数为promise对象的函数,在异步请求结束之后,使用put方法派发新任务并携带异步请求结果到reducer中,更新数据。注意此处getListAction函数是我们模仿异步请求的的promise对象,实际开发中是异步api请求。
import {take,fork,put,call} from 'redux-saga/effects'
function *watchSaga(){
while(true){
// take函数只要有人发action就能监听到 监听组件发来的action
// fork 同步处理异步函数
yield take('get-list')
yield fork(getList)
}
}
// generator异步处理函数
function *getList(){
// call函数发送异步请求
let res=yield call(getListAction) // 返回值是promise对象的函数
// put 函数发出新的action
yield put({
type:"change-list",
data:res
})
}
function getListAction(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(['111','222','333'])
},2000)
})
}
export default watchSaga
(4) store.js中创建实例
createSagaMiddleWare方法创建对象SagaNiddleWare后,放入中间件中,引入自定义的wacthSage方法,使用SagaNiddleWare.run方法运行saga监听
import {createStore,applyMiddleware} from 'redux'
import reducer from './reducer'
import createSagaMiddleWare from 'redux-saga'
const SagaNiddleWare =createSagaMiddleWare()
const store=createStore(reducer,applyMiddleware(SagaNiddleWare))
import watchSaga from './saga'
SagaNiddleWare.run(watchSaga) // saga监听
export default store
(5) 执行结果
我们在reducer中打印执行action,两秒钟之后会有新的派发任务接收到,并携带参数
四、核心API
(1)take
监听视图层传入的Action,检测是否与自身匹配,匹配则执行
function *watchSaga(){
while(true){
// take函数只要有人发action就能监听到 监听组件发来的action
yield take('get-list')
}
}
(2)fork
异步非阻塞调用 在getList函数中,对于Ganerator来说, call函数需要执行异步请求,那么必须等待Promise异步请求执行结束并返回结果,call操作是阻塞的,而fork的作用是不必等待call函数执行完毕,不会影响接下来的其他任务的执行。
function *watchSaga(){
while(true){
// fork 同步处理异步函数
yield fork(getList)
}
}
(3)call
异步阻塞调用 将异步函数作为第一个参数传入call函数中,等待异步请求执行结束,并返回res 个人认为类似async-awaite
let res=yield call(getListAction) // 返回值是promise对象的函数
可以多次调用call函数处理多个异步请求函数,并能将上一个异步请求结果传递到下一个异步请求中
let res1=yield call(getListAction1)
let res2=yield call(getListAction2,res1)
funtionc getListAction2(data){
}
(4)put
相当于dispatch,推入新的Action到reducer中
yield put({
type:"change-list",
data:res
})
(5) tackEvery
每监听一次Action,匹配到Action便会执行一次
function *watchSaga(){
while(true){
yield tackEvery('get-list')
}
}
(6) takeLatest
监听匹配的Action,同时只执行最后一次匹配的Action,在此之前的异步请求将会停止。
function *watchSaga(){
while(true){
yield tackEvery('get-list')
}
}
(7)all([]...effects)
合并saga监听函数
import {all} from 'redux-saga/effects'
import watchSaga1 from './watchSaga1'
import watchSaga2 from './watchSaga2'
function *watchSaga(){
while(true){
yield all([watchSaga1(),watchSaga2()])
}
}
expory default watchSaga
五、总结
Redux-saga其实本身只是一个Redux中间件,使我们能够更优雅的管理Redux异步请求。它将异步请求从Action中抽离,使得Action更为纯粹,其次使用Generator对异步请求进行处理,更为方便以及易于管控。