redux-saga工做原理

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

saga分类react

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

saga 组成

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

  • put 派发一个动做app

  • takeEvery 监听每一个动做异步

  • call 执行一个动做函数

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

  • effectthis

综上所述咱们先有个rootSaga做为惟一入口spa

src/sagas.jscode

// 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.jscomponent

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
}
复制代码
相关文章
相关标签/搜索