redux-saga工作原理

  • sages 采用 Generator 函数来 yield Effects(包含指令的文本对象)
  • Generator 函数的作用是可以暂停执行,再次执行的时候从上次暂停的地方继续执行
  • Effect 是一个简单的对象,该对象包含了一些给 middleware 解释执行的信息。
  • 你可以通过使用 effects API 如 fork,call,take,put,cancel 等来创建 Effect。

saga分类

  1. worker saga 做左右的工作,如调用API,进行异步请求,获取异步封装结果
  2. watcher saga 监听被dispatch的actions,当接受到action或者知道其被触发时
  3. 调用worker执行任务 root saga 立即启动saga的唯一入口

saga 组成

  • take 等待一个动作发生,只发生一次

  • put 派发一个动作

  • takeEvery 监听每个动作

  • call 执行一个动作

  • index.js 导出createSagaMiddeware函数,这个函数执行完返回一个中间件

  • effect

综上所述我们先有个rootSaga作为唯一入口

src/sagas.js

// import {takeEvery,put,all,call} from 'redux-saga/effects';
// import * as types from './store/action-types';
// const delay=ms => new Promise(function(resolve,reject){
//     setTimeout(function(){
//         resolve()
//     },ms)
// })
// function* add(dispatch,action,all){
//     // setTimeout(function(){
//     //     dispatch({type:types.ADD})
//     // },1000)
//     帮我执行这个动作
//     yield call(delay,5000)
//     帮我派发这个动作
//     yield put({type:types.ADD})
// }
// function* logger(action){
//     console.log(action);
    
// }
// function* watchLogger(){
//     yield takeEvery('*',logger)
// }
// function* watchAdd(){
//     yield takeEvery(types.ADD_ASYNC,add)
// }
// export function* rootSaga({getState,dispatch}){
//     yield all([watchAdd(),watchLogger()])  ;
// }
// import {take,takeEvery,put,all,call} from 'redux-saga/effects';
import {takeEvery,take,put,call} from './redux-saga/effects';
import * as types from './store/action-types';

// export function* rootSaga(){
// 	// yield {type:'take',acionType:ADD_ASYNC}
// 	// while(true){
// 		let action=yield take(types.ADD_ASYNC);
// 		yield put({type: types.ADD});
// 	// }
// }
const delay=ms => new Promise(function(resolve,reject){
    setTimeout(function(){
        resolve()
    },ms)
})
function* add(){
    // setTimeout(function(){
    //     dispatch({type:types.ADD})
    // },1000)
    yield call(delay,1000)
    yield put({type:types.ADD})
}
export function* rootSaga(){
	let action=yield takeEvery(types.ADD_ASYNC,add);
}
复制代码

src/components/Counter.js

import React,{Component} from 'react'
import {connect} from 'react-redux';
import actions from '../store/actions';
class Counter extends Component{
    render() {
        return (
            <div>
                <p>{this.props.number}</p>
                <button onClick={this.props.increment}>+</button>
            </div>
      )
  }
}
export default connect(
    state => state,
    actions
)(Counter);
复制代码

src/store/index.js

import {createStore, applyMiddleware} from 'redux';
import reducer from './reducer';
import createSagaMiddleware from 'redux-saga';
import {rootSaga} from '../saga';
let sagaMiddleware=createSagaMiddleware();//返回一个中间件
let store=applyMiddleware(sagaMiddleware)(createStore)(reducer);//应用中间件
sagaMiddleware.run(rootSaga,store);//执行Genrator函数
window.store=store;
export default store;
复制代码

src/store/actions.js

import * as types from './action-types';
export default {
    increment() {
        return {type:types.INCREMENT}
    }
}
复制代码

action-types.js #

export const INCREMENT='INCREMENT';
复制代码

reducer.js

import * as types from './action-types';
export default function (state={number:0},action) {
    switch(action.type){
        case types.INCREMENT:
            return {number: state.number+1};
        default:
            return state;
    }
}
复制代码

** src/saga.js #**

import {takeEvery,put} from 'redux-saga/effects';
import * as types from './store/action-types';
const delay=ms => new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve();
    },ms);
});
export function* increment(dispatch) {
    yield delay(1000);
    yield put({type:types.INCREMENT});
}

export function* rootSaga({getState,dispatch}) {
    //takeEvery接受每一个将停派发给仓库的动作,每一个INCREMENT_ASYNC动作,当作发生的时候,如果对应执行对应的监听生成器
    yield takeEvery(types.INCREMENT_ASYNC,increment,dispatch);
}
复制代码
redux-saga实现原理

index.js

function createChannel() {
    //对象每一个动作对应一个回调函数
    let takers={};
    function subscribe(actionType,cb) {
        takers[actionType]=cb;
    }
    function publish(action) {//{type:ADD}
        //看看有没有人监听
        let taker=takers[action.type]
        if (taker) {//如果有执行监听函数并且删除监听函数
            let tmp=taker;
            delete taker[action.type];
            tmp(action);        
        }
    }
    return {subscribe,publish};
}
let channel=createChannel();   
function createSagaMiddelware() {
    function sagaMiddelware({getState,dispatch}){                
        //负责把gernerator执行完毕  co库 rootSaga
        function run(iterator){//(rootSaga,store)
            //执行得到迭代器,next得到值,可能是器也可能是迭代器
            let it = typeof iterator == 'function'?iterator():iterator;       
            function next(input){
                let {value: effect,done}=it.next(input);             
                if(!done){//如果迭代器没有完成
                    //如果这个属性是个函数,他就是genrator
                    if(typeof effect[Symbol.iterator] == 'function'){
                        run(effect);
                        next();
                    }else{
        
                    }
                    switch(effect.type){
                        //等待一个动作发生,相当于注册一个监听
                        case 'take':
                            let {actionType}=effect;
                            channel.subscribe(actionType,next);
                            break;
                        case 'put':
                            let {action}=effect;
                            dispatch(action);
                            next(action);
                            break;
                        case 'fork':
                            let {worker}=effect;
                            run(worker);
                            next();
                            break;
                        case 'call':
                            let {fn,args}=effect;
                            fn(...args).then(next);
                            break;
                        default:
                            break;
                    }
                }
            }
            next()
        }
        sagaMiddelware.run = run;
        return function(next){
            //下面的是真正的dispatch函数
            return function(action){
                channel.publish(action)
                next(action)
            }  
        }
        
    }
    return sagaMiddelware;
}
export default createSagaMiddelware;
复制代码

effect.js

//这里所有的函数都会返回一个effect,effect就是一个普通对象
//effect对象都有一个type属性
function take(actionType) {
	return {
		type: 'take',
		actionType
	}
}
function put(action) {
	return {
		type: 'put',
		action
	}
}
function fork(worker) {
	return {
		type: 'fork',
		worker
	}
}
function call(fn,...args) {
	return {
		type: 'call',
		fn,
		args
	}
}
//监听每一个动作类型,当此动作发生的时候执行对应的worker
//takeEvery它会单开一个任务,并不会阻塞当前saga
function* takeEvery(actionType,worker) {
	yield fork(function* () {
		while (true) {
			let action=yield take(actionType);
			yield worker(action);
		}
	})
}
//takerEvery的结果是一个迭代器
//iterator
export {
	take,
	put,
	takeEvery,
	call
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值