zoukankan      html  css  js  c++  java
  • react系列(六)Redux Saga

    在Redux中常要管理异步操作,目前社区流行的有Redux-Saga、Redux-thunk等。在管理复杂应用时,推荐使用Redux-Saga,它提供了用 generator 书写类同步代码的能力。
    在讲解 ReduxSaga 前,先要说明一下 Redux Middleware 的概念。

    Middleware

    它提供的是位于 action 被发起之后,到达 reducer 之前的扩展点。

    如果写过 Koa 或者 Express ,就会很容易理解 Middleware 的概念。
    可以说,Middleware 是一种置于一个调用发起到被处理这段过程之间的函数。它可以对发起的调用进行处理,处理后直接返回,或者调用下一个中间件。
    在Redux中,使用柯里化函数声明中间件,一个简单的例子如下:

    /**
     * 记录所有被发起的 action 以及产生的新的 state。
     */
    const logger = store => next => action => {
      console.group(action.type)
      console.info('dispatching', action)
      let result = next(action)
      console.log('next state', store.getState())
      console.groupEnd(action.type)
      return result
    }
    

    然后需要将它应用到Redux上

    import { createStore, combineReducers, applyMiddleware } from 'redux'
    
    const todoApp = combineReducers(reducers)
    const store = createStore(
      todoApp,
      // applyMiddleware() 告诉 createStore() 如何处理中间件
      applyMiddleware(logger, crashReporter)
    )
    

    之后dispatch的每一个action都会触发log中间件。
    更详细的用法在Redux文档里说明得很详细了,Redux-Middleware

    使用Redux Saga

    先定一个小目标,写一个异步增加的demo。
    先来创建一个sagas.js文件,用来存放我们的sagas。

    import { delay } from 'redux-saga'
    import { put, takeEvery } from 'redux-saga/effects'
    
    export function* plusAsync() {
      yield delay(1000)
      yield put({ type: 'PLUS' })
    }
    
    // 在dispatch到store并且匹配pattern的每一个action上派生一个saga
    export function* watchPlusAsync() {
      yield takeEvery('PLUS_ASYNC', incrementAsync)
    }
    

    在上篇例子的基础上,增加一个按钮,用来派发PLUS_ASYNC事件。

     <button onClick={dispatch({type: 'PLUS_ASYNC'}}>{"plusAsync"}</button>
    

    在使用时,经常需要将多个sagas合并成一个。

    import { all } from 'redux-saga/effects'
    
    // ...
    
    export default function* rootSaga() {
      yield all([
        watchPlusAsync()
      ])
    }
    

    最后,需要创建saga Middleware。并将中间件应用到redux上。

    import { createStore, applyMiddleware } from "redux";
    
    // ...
    
    // 创建一个Store
    const sagaMiddleware = createSagaMiddleware()
    const store = createStore(
      counter,
      applyMiddleware(sagaMiddleware)
    )
    
    // 运行sagas
    sagaMiddleware.run(allSagas);
    

    常用API说明

    middleware.run(saga, ...args)

    动态地运行 saga。只能 用于在 applyMiddleware 阶段 之后 执行 Saga。

    takeEvery(pattern, saga, ...args)

    在发起(dispatch)到 Store 并且匹配 pattern 的每一个 action 上派生一个 saga。

    pattern用来匹配对应的TYPE,对应到指定的saga处理函数上。
    args就是相当于指定给saga的参数数组,并且takeEvery会将action拼到最后一个参数上。

    takeLatest(pattern, saga, ...args)

    在发起到 Store 并且匹配 pattern 的每一个 action 上派生一个 saga。并自动取消之前所有已经启动但仍在执行中的 saga 任务。

    这个函数可以说是takeEvery的防抖版本。
    具体例子可以查看这里-redux_saga_example

    put(action)

    创建一个 Effect 描述信息,用来命令 middleware 向 Store 发起一个 action。 这个 effect 是非阻塞型的,并且所有向下游抛出的错误(例如在 reducer 中),都不会冒泡回到 saga 当中。

    all

    创建一个 Effect 描述信息,用来命令 middleware 并行地运行多个 Effect,并等待它们全部完成。这是与标准的 Promise#all 相当对应的 API。

    更多API请查看Saga文档

    总结

    saga的用法比较简单,分为4步。

    1. 创建saga并且将使用takeEvery给每一个符合patternaction都增加一个对应的saga处理函数。
    2. 使用all导出编写的saga。
    3. 创建saga中间件,在使用redux创建store时,应用saga中间件。
    4. 运行中间件。

    感谢阅读。

  • 相关阅读:
    排列组合STL实现——pku1731
    迷宫搜索变型——【USACO5.2.1】蜗牛的旅行
    知道地球两点算距离——fzu2016
    最长递增子序列——pku2533
    dfs+dp——[Usaco2008 Mar]Cow Travelling游荡的奶牛
    最长不降子序列变型——[Usaco2008 Feb]Eating Together麻烦的聚餐
    规律题——[Usaco2008 Oct]建造栅栏
    简单dp——[Usaco2008 Mar]River Crossing渡河问题
    poj1317
    poj1068
  • 原文地址:https://www.cnblogs.com/liuyongjia/p/9905523.html
Copyright © 2011-2022 走看看