redux-saga

中文文档地址

特点:

  1. 纯净
  2. 强大
  3. 灵活
    saga流程图

在saga任务中,如果yield了一个普通数据,saga不做任何处理,仅仅将数据传递给yield表达式(把得到的数据放到next参数中),因此,在saga中,yield一个普通数据没有什么意义

saga需要你在yield后面放上一些合适的saga指令(saga effects),如果放的是指令,saga中间件会根据指令来做出不同的处理,以控制整个任务流程

import { createStore, applyMiddleware } from 'redux'
// import * as actionType from '../action/action-type'
import * as usersAction from './action/student/usersAction'
import * as numberAction from './action/counter/number-action'
// import createStore from '../redux/createStore'
import { bindActionCreators, combineReducers } from '../redux/index'
import { v4 as uuid4 } from 'uuid'
import loginUser from './reducer/loginUser'
import numberReducer from './reducer/numberReducer'
import usersReducer from './reducer/usersReducer'
import logger from 'redux-logger';
import thunk from 'redux-thunk'
import createSagaMiddleware from 'redux-saga'
import { all } from 'redux-saga/effects'
import counterTask from '../saga/counterTask'

// const store = createStore(loginUser, { id: 1234, name: "qian" })

// console.log(store.getState());

// store.dispatch(LoginUserActions.getLoginUser({ age: 5678, sex: "meale" , name:"liu"}))

// const addUser = {
//     id: 3,
//     name: "zhangsan",
//     age: 18,
//     sex: "meale"
// }

//创建共享仓库
const reducers = combineReducers({
    loginUser: loginUser,
    numberReducer: numberReducer,
    usersReducer: usersReducer
})
/**
 * saga任务
 */
export function* sagaTask() {
    yield all([counterTask()]);
    console.log("任务完成");
}


//创建saga中间件
const sagaMiddleware = createSagaMiddleware();

// 创建中间件方法1
const store = createStore(reducers, applyMiddleware(sagaMiddleware, logger));

//启动saga任务
sagaMiddleware.run(sagaTask);

const bindAction = bindActionCreators(numberAction, store.dispatch)

bindAction.getIncreaseAction();


// 创建中间件方法2
// const store = applyMiddleware(logger1, logger2)(createStore)(reducers, {loginUser:{ id: 1234, name: "qian" }, numberReducer:10})
//第一个参数,时action创建函数的合并对象,,第二个参数时仓库的dispatch函数
//得到一个新对象,新对象中的属性名与第一个参数的属性名完全一致。
// const bindAction = bindActionCreators(usersAction, store.dispatch)

// 获取到action并且直接分发,不用在调用dispatch
// bindAction.getusers();

// bindAction.createAddUserAction(addUser);

// bindAction.getusers();

// bindAction.updateUserAction(3, {
//     id: 3,
//     name: "lishi",
//     age: 28,
//     sex: "female"
// });

saga指令本质上就是一个函数,该函数调用后,会返回一个指令对象,saga会接收到该指令对象进行各种处理,yield会返回一个完整的action

指令内容
take【会造成阻塞】监听某个action,如果action发生了改变,则会进行下一步处理,take指令仅监听一次,yield得到的是完整的action对象。pattern为空 或者 * ,将会匹配所有发起的action。 pattern是一个函数,action 会在 pattern(action) 返回为 true 时被匹配
all【阻塞】该函数传入一个数组,数组中放入生成器,saga会等待所有生成器全部完成后才会进行下一步处理。
takeEvery不断的监听某个action,当某个action到达之后,运行一个函数,takeEvery永远不会结束当前的生成器。
delay【阻塞】阻塞指定的毫秒数。
import { takeEvery, take, delay } from 'redux-saga/effects'
import * as actionType from '../store/action/action-type'
function* increase() {
    yield delay(2000)
    console.log("increase运行")
}

function* decrease() {
    yield delay(2000)
    console.log("decrease运行")
}


export default function* counterTask() {
    console.log("conterTask运行");
    let data = yield takeEvery(actionType.INCREASE, increase);
    data = yield takeEvery(actionType.DECREASE, decrease);
    console.log(data);
}

		运行结果:
		action increase @ 10:59:12.572
		prev state {loginUser: null, numberReducer: 10, usersReducer: Array(0)}
		action     {type: "increase"}
		next state {loginUser: null, numberReducer: 11, usersReducer: Array(0)}
		action decrease @ 10:59:12.575
		prev state {loginUser: null, numberReducer: 11, usersReducer: Array(0)}
		action     {type: "decrease"}
		next state {loginUser: null, numberReducer: 10, usersReducer: Array(0)}
		increase运行(两秒后运行)
		decrease运行(两秒后运行)
指令内容
put用于重新触发action,相当于dispatch触发action。
import { getIncreaseAction } from '../store/action/counter/number-action'

export default function* counterTask() {
    console.log("conterTask运行");
    const result = yield put(getIncreaseAction());
    console.log(result)
    // let data = yield takeEvery(actionType.INCREASE, increase);
    // data = yield takeEvery(actionType.DECREASE, decrease);
    // console.log(data);
}

运行结果:
conterTask运行
action increase @ 11:16:50.651
prev state {loginUser: null, numberReducer: 10, usersReducer: Array(0)}
action     {type: "increase", @@redux-saga/SAGA_ACTION: true}
next state {loginUser: null, numberReducer: 11, usersReducer: Array(0)}
{type: "increase", @@redux-saga/SAGA_ACTION: true}type: "increase"@@redux-saga/SAGA_ACTION: true__proto__: Object
任务完成
指令内容
call【可能阻塞】 用于副作用函数调用(通常是异步)。
apply【可能阻塞】apply的作用和call是一样,只有传入的参数不一样,第一个参数传入的是this的指向,第二个参数传入调用的函数,第三个是传入函数的参数,apply为一个数组,call为字符串。
import { takeEvery, take, delay, put, call, apply } from 'redux-saga/effects'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'
function* increase() {
    yield delay(2000)
    console.log("increase运行")
}

function* decrease() {
    yield delay(2000)
    console.log("decrease运行")
}

function asyncGetStudent(name, age) {
    setTimeout(() => {
        console.log("call 调用副作用函数");
        console.log(name, age)
        return { name: name, age: age }
    }, 3000)
}


export default function* counterTask() {
    console.log("conterTask运行");
    const result = yield call(asyncGetStudent, "qian", 18);
    yield apply(null, asyncGetStudent, ["ren", 18])
    console.log(result)
}

运行结果:
call 调用副作用函数
qian 18
call 调用副作用函数
ren 18
指令内容
select查询整个仓库当前的状态。返回值为当前仓库的状态。
import { takeEvery, take, delay, put, call, apply, select } from 'redux-saga/effects'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'


export default function* counterTask() {
    console.log("conterTask运行");
    const state = yield select();
    console.log(state)
}
运行结果:
conterTask运行
{loginUser: null, numberReducer: 10, usersReducer: Array(0)}
指令内容
cps【可能阻塞】用于调用那些传统的回调方式的异步函数
import { takeEvery, take, delay, put, call, apply, cps } from 'redux-saga/effects'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'
function asyncGetStudent(callback) {
    setTimeout(() => {
        if(Math.random() > 0.5){
            callback(null, {
                cont:100,
                datas:[
                    {name:"qian", age:20 }
                ]
            })
        }
        else{
            callback(new Error("callback 出错啦"), null)

        }

       
    }, 3000)
}


export default function* counterTask() {
    console.log("conterTask运行");
    const result = yield cps(asyncGetStudent);
    console.log(result)
}

运行结果:3秒后
{cont: 100, datas: Array(1)}cont: 100datas: Array(1)0: {name: "qian", age: 20}length: 1__proto__: Array(0)__proto__: Object
指令内容
fork用于开启一个新的任务,该任务不会阻塞,该函数需要传递一个生成器函数,相当于新开了一个任务线。fork返回了一个对象,类型为Task
cancel用于取消一个或者多个任务, 实际上,用的是generator.return来做的,cancel可以不传参数,如果不穿参数,则取消自身的任务线。
takeLastest功能和takeEvery一致,但是,会自动取消之前开启的任务
import { takeEvery, delay, put, fork, take, cancel } from 'redux-saga/effects'
import { getIncreaseAction } from '../store/action/counter/number-action'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'
let task;

function* asyncAutoIncrease() {
    while (true) {
        yield take(actionType.AUTOINCREASE)
        //停止之前的任务
        if (task) {
            yield cancel(task);
        }
        task = yield fork(function* () {
            while (true) {
                yield delay(2000);
                yield put(getIncreaseAction());
            }
        })
    }
}

function* asyncStopAutoIncrease() {
    if (task) {
        yield cancel(task);
    }
}

export default function* counterTask() {
    console.log("conterTask运行");
    yield fork(asyncAutoIncrease);
    yield takeEvery(actionType.STOPAUTOINCREASE, asyncStopAutoIncrease);
    console.log("正在监听 asyncAutoIncrease")
}
import { cancel, delay, fork, put, take } from 'redux-saga/effects'
import { getIncreaseAction } from '../store/action/counter/number-action'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'
let task;

/**
 * 自动增加和停止的流程控制
 * 流程:自动增加 -> 停止 -> 自动增加 -> 停止
 * 
 */
function* autoTask() {
    while (true) {
        yield take(actionType.AUTOINCREASE)
        task = yield fork(function* () {
            while (true) {
                yield delay(2000);
                yield put(getIncreaseAction());
            }
        })
        yield take(actionType.STOPAUTOINCREASE);
        yield cancel(task);
    }
}

export default function* counterTask() {
    console.log("conterTask运行");
    yield fork(autoTask)
    console.log("正在监听 asyncAutoIncrease")
}
指令内容
cancelled判断当前任务先是否被取消
import { cancel, cancelled, delay, fork, put, take } from 'redux-saga/effects'
import { getIncreaseAction } from '../store/action/counter/number-action'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'
let task;

/**
 * 自动增加和停止的流程控制
 * 流程:自动增加 -> 停止 -> 自动增加 -> 停止
 * 
 */
function* autoTask() {
    while (true) {
        yield take(actionType.AUTOINCREASE)
        task = yield fork(function* () {
            try {
                while (true) {
                    yield delay(2000);
                    yield put(getIncreaseAction());
                }
            } finally {
                //判断当前的fork任务是否结束,结束返回true
                if(yield cancelled()){
                    console.log("任务被取消了")
                }
            }
            
        })
        yield take(actionType.STOPAUTOINCREASE);
        yield cancel(task);
    }
}

export default function* counterTask() {
    console.log("conterTask运行");
    yield fork(autoTask)
    console.log("正在监听 asyncAutoIncrease")
}
指令内容
race【阻塞】竞赛,可以传递多个指令,当其中任何一个指令结束后,会直接结束,于Promise.race类似,返回的结果是最先完成的结果,然后会自动取消其他的任务
import { call, fork, race } from 'redux-saga/effects'
import { getIncreaseAction, getDecreaseAction } from '../store/action/counter/number-action'
import * as actionType from '../store/action/action-type'
// import { getIncreaseAction } from '../store/action/counter/number-action'
let task;

function asyncAction() {
    let duration = Math.floor(Math.random() * 4000 + 1000);
    console.log(duration);
    return new Promise(resolve => {
        setTimeout(function () {
            if (Math.random() > 0.5){
                resolve(getIncreaseAction())
            }
            else{
                resolve(getDecreaseAction())
            }
        }, duration)
    })

}

/**
 * 返回的结果是最先完成的结果,然后会自动取消其他的任务
 */
export default function* counterTask() {
    const result = yield race({
        action1: yield call(asyncAction),
        action2: yield call(asyncAction)
    })
    console.log(result);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值