redux-thunk vs redux-saga的状态管理

状态管理

写这篇笔记更正以前理解的误区,背景呢,一次需求中实现根据参数 itemId 等分页信息拉取接口至少5次, 并在state 中并保存合并对应itemId下的数据, 这里有两个步骤1,每次请求的数据在赋值给state以前 ,要获取到原有state中的值; 2,合并操做。那如何在reduce 中获取到原有state的值呢, 就是状态管理了.react

redux

redux 自己很是简单,它只有三个核心概念:state、action 和 reducer, 直接看官网就能够了, 或者网上成堆的10 分钟理解 Redux。 将须要修改的 state 都存入到 store 里, 发起一个 action 用来描述发生了什么,用 reducers 描述 action 如何改变 state tree 。所以只有 reducer 能修改 state。redux 经过这些约束,让数据的变化变得可预测、可回溯。在建立 store 的时候须要传入 reducer,真正能改变 store 中数据的是 store.dispatch API。能够采用两种中间件redux-thunk 和redux-saga。 固然也能够直接使用ant design pro是基于UmiJS、dva,而 dva 也是基于 redux、redux-saga 和 react-router 的进一步封装。git

redux-thunk

redux-thunk 中间件能够容许你写的 action creator 函数能够返回 action 对象的同时,也能够返回一个函数。函数传递两个参数 (dispatch,getState), 在函数体内进行业务逻辑的封装, getState() 方法获取 state这个中间件能够被用来延缓分发 action 的时机,或者实现只在知足某个条件的时候才触发 action。简而言之,中间件都是对 store.dispatch () 的加强。如下是官网的一个例子github

import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';

const store = createStore(
    reducers, 
    applyMiddleware(thunk)
);


// 并且可使用 Promise 来控制数据流。

function makeSandwichesForEverybody() {
  return function (dispatch, getState) {
    if (!getState().sandwiches.isShopOpen) {
    
		
      // 返回 Promise 并非必须的,但这是一个很好的约定,
      // 为了让调用者可以在异步的 dispatch 结果上直接调用 .then() 方法。

      return Promise.resolve()
    }

    // 能够 dispatch 普通 action 对象和其它 thunk,
    // 这样咱们就能够在一个数据流中组合多个异步 action。

    return dispatch(
      makeASandwichWithSecretSauce('My Grandma')
    ).then(() =>
      Promise.all([
        dispatch(makeASandwichWithSecretSauce('Me')),
        dispatch(makeASandwichWithSecretSauce('My wife'))
      ])
    ).then(() =>
      dispatch(makeASandwichWithSecretSauce('Our kids'))
    ).then(() =>
      dispatch(getState().myMoney > 42 ?
        withdrawMoney(42) :
        apologize('Me', 'The Sandwich Shop')
      )
    )
  }
}

复制代码

以上就是异步 Action ,thunk 是判别 action 的类型,若是 action 是函数,就调用这个函数,可是函数的内部能够多种多样。好比下面是一个获取matching 中图片下面的信息的异步操做所对应的 action,然而须要为每个异步操做都如此定义一个 action,显然 会有大量的action, 而且action 不易维护, 这是action 的反作用,也正是thunk 的缺点仅仅调用的函数。redux

redux-saga

官网上的描述redux-saga 是一个用于管理应用程序 Side Effect(反作用,例如异步获取数据,访问浏览器缓存等)的 library,它的目标是让反作用管理更容易,执行更高效,测试更简单。 粗浅的使用后的感觉是很强大-各类状况下的流程控制都有对应的api,这些api保证了更简便的流程控制和易于测试的好处,因 thunk 插件仍是须要你本身来写promise来保证各类异步和异常。那redux-saga 中间件中如何获取state呢,更简单select(selector, ...args)api

const keyList = yield select(state => {});

复制代码

几种经常使用的用法

Sagas 被实现为 Generator functions,一旦 Promise 被 resolve,middleware 会恢复 Saga 接着执行,直到遇到下一个 yield。 点击获取如下详细的demo例子promise

  • put 用于建立 dispatch Effect。
  • takeEvery(pattern, saga, ...args)在发起(dispatch)到 Store 而且匹配 pattern 的每个 action 上派生一个 saga。
  • call 用于建立 Effect。发起异步或者同步操做
  • select 用于建立一个 Effect, 返回当前 Store state 上的一部分数据
  • fork 建立一个 Effect,用来命令 middleware 以 非阻塞调用 的形式执行 fn
  • cacel 建立一个 Effect,用来命令 middleware 取消以前的一个分叉任务-以前 fork 指令返回的 Task 对象
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'

//...
import { demoSaga } from './demoSagas'

const store = createStore(
  reducer,
  applyMiddleware(createSagaMiddleware(demoSaga))
)

import { delay } from 'redux-saga'
import { put, takeEvery } from 'redux-saga/effects'



// demoSagas.js 

// Our worker Saga: 将执行异步的 获取用户信息
export function* getUser() {
   const user = yield call(fetch, {
      // method: "POST"
      resource: ''
    });
}

// Our watcher Saga: 
const watchGet  = function* watchGet() {
  yield takeEvery(getUserRequested, getUser);
}


cnost getActions = {
  [getUserRequested]: state => {
    return {
      ...state,
      isLogging: true
    };
  },
  [getUserSucceed]: (state, { payload: { avatar, name, email } }) => {
    return {
      ...state,
      isLogging: false,
      user: {
        avatar,
        name,
        email
      }
    };
  },
  [getUserFailed]: state => {
    return {
      ...state,
      isLogging: false
    };
  }
};


// rootSaga.js 

export default function* rootSaga() {
import { all, call } from 'redux-saga/effects';
import { watchAppSagas } from './reducers/demoReducer';

export const sagas = function* rootSaga() {
  yield all(
    [
      ...watchAppSagas,
    ].map(call)
  );
};



复制代码
相关文章
相关标签/搜索