redux-saga 是什么?_张驰Zhangchi的博客-程序员宅基地

技术标签: python  java  vue  中间件  软件研发  javascript  

前言

在使用react redux的时候,会经常遇到需要处理异步action的情况。处理异步action的方法有几种。其中redux-thunk,redux-saga都是处理异步action的中间件。利用这些中间件可以很好的达到我们预期效果

redux-saga

redux-saga是一个用于管理应用程序 Side Effect(副作用,例如异步获取数据,访问浏览器缓存等)的 library,它的目标是让副作用管理更容易,执行更高效,测试更简单,在处理故障时更容易。

个人是这么理解redux-saga的,在app中注入redux-saga中间件后,saga effects函数中对相对应的action进行监听,在代码中执行触发dispatch 对应action的时候,saga的effects 函数会对其进行拦截处理,中途进行一些异步、同步、或者是执行调用其他effects函数。在effects函数中,可以同步的方式书写异步代码。相对于redux-thunk,saga的优势在于effects函数中对各种异步的处理比较方便和容易拓展。

计数器demo例子

Counter 组件

import React, { Component, PropTypes } from 'react'

const Counter = ({ value, onIncrement, onDecrement, onIncrementAsync }) =>
      <div>
        <button onClick={onIncrement}>
          Increment
        </button>
        {' '}
        <button onClick={onDecrement}>
          Decrement
        </button>
        <button onClick={onIncrementAsync}>
          delay Increment
        </button>
        <hr />
        <div>
          Clicked: {value} times
        </div>
      </div>

Counter.propTypes = {
  value: PropTypes.number.isRequired,
  onIncrement: PropTypes.func.isRequired,
  onDecrement: PropTypes.func.isRequired,
  onIncrementAsync:  PropTypes.func.isRequired
}
export default Counter

main.js

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import rootSaga from './saga'
import Counter from './Counter'
import reducer from './reducers'

const sagaMiddleware = createSagaMiddleware()
const store = createStore(
  reducer,
  applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(rootSaga)
const action = type => store.dispatch({type})

function render() {
  ReactDOM.render(
    <Counter
      value={store.getState()}
      onIncrement={() => action('INCREMENT')}
      onDecrement={() => action('DECREMENT')}
      onIncrementAsync={() => action('INCREMENT_ASYNC')} />,
    document.getElementById('root')
  )
}

render()
store.subscribe(render)

saga.js

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

export function* incrementAsync() {
    yield delay(1000)
    yield put({ type: 'INCREMENT' })
}
export function* watchIncrementAsync() {
    yield takeEvery('INCREMENT_ASYNC', incrementAsync)
}
export default function* rootSaga() {
    yield all([
        watchIncrementAsync()
    ])
}

在计数器中有三个按钮 IncrementDecrementDelay Increment点击Increment,计数马上加1,点击Decrement,计数马上减1,点击Delay Increment计数延迟1秒加1

原理解析在saga中,对于INCREMENT_ASYNC这个action进行了监听,如果触发了这个action则会执行saga中的incrementAsync函数,在该函数中,有delay延迟函数。yield delay(1000)的意思是等待延迟1秒,然后执行yield put(…),执行触发INCREMENTaction,然后触发reducer 对state的值的修改。

整个流程 监听INCREMENT_ASYNC,触发INCREMENT_ASYNC,执行incrementAsync,dispatchINCREMENT,最后修改state,触发UI更新。在saga的effects函数中可以对异步处理的结果进行再次处理整合,最后再派发执行下一步。整个流程是有序执行可监控的。这样我们就简单理解了redux-saga的原理和流程,进一步学习redux-saga则需要对API有更深入的了解

进阶学习redux-saga

  • take
  • fork
  • takeEvery
  • takeLatest

takeLatest & takeEvery 是监听action,一遍一遍执行,不会停止。takeLatest与takeEvery的区别在于,如果同个action多次触发,takeLatest只会执行最后一个action,往前的action会取消调用,而takeEvery则每个action均会执行调用。take则只执行一次。fork则在后台建立任务监听,非阻塞主流程。所以会经常使用 fork+ while(true)+take的方式实现可控制的effect函数。查看例子

import { fork, call, take, put } from 'redux-saga/effects'
import Api from '...'

function* authorize(user, password) {
  try {
    const token = yield call(Api.authorize, user, password)
    yield put({type: 'LOGIN_SUCCESS', token})
  } catch(error) {
    yield put({type: 'LOGIN_ERROR', error})
  }
}

function* loginFlow() {
  while(true) {
    const {user, password} = yield take('LOGIN_REQUEST')
    yield fork(authorize, user, password)
    yield take(['LOGOUT', 'LOGIN_ERROR'])
    yield call(Api.clearItem('token'))
  }
}

收到LOGIN_REQUEST的action的时候,会进入loginFLow,然后提交检验authorize,这个过程是后台任务执行的,此时如果触发了LOGOUTaction,函数不会被阻塞,会执行call(Api.clearItem('token'))。redux-saga的高级用法就是通过这些API能够很好的控制异步流程。

参考资料

原文链接: https://www.xiaolai.cc/2019/03/26/react-saga/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/terrychinaz/article/details/114823603

智能推荐

Alexa 账号注册的多种方法_alexa如何申请账号-程序员宅基地

进入官网:https://www.alexa.com/点击:START YOUR FREE TRIAL有三大主功能分类选择需要的功能类:点击进入:TRAY 7 DAYS FREE出现注册页面:输入相关信息 :点击 :Create an Account直接需要填写信息及验证支付银行卡方式。顺利填写后即可完成该项目的注册。..._alexa如何申请账号

jmeter安装及使用基本教程_jmeter需要安装java吗-程序员宅基地

一、安装1.安装jdk,配置环境变量附:JRE(Java Runtime Environment ) Java运行环境,用来运行JAVA程序的。JDK(Java Development Kit) Java开发工具包,包含JRE。因此只需要下载安装JDK即可中。JDK是Sun Microsystems针对Java开发员的产品,JSP运行环境需要JDK的支持。JDK 是整个Java的核心,..._jmeter需要安装java吗

国产GBase数据库(南大通用)官方学习笔记大全_南大通用数据库的数据类型-程序员宅基地

GBase数据库的学习笔记之——“数据类型”_南大通用数据库的数据类型

树莓派3B安装python3 opencv环境_cabbagel的博客-程序员宅基地

树莓派3b,若干年前买的,软件具体配置不记得。python缺省版本为3.53。直接用pip命令安装不成功,显示一堆的红字。update/upgrade一下。耗时挺长,再安装,成功了。如下图。sudo apt-get updatesodu apt-get upgradesudo pip3 install opencv-python...

文件上传&ContentType请求格式-程序员宅基地

一、文件上传1、通过表单形式上传文件1 <form action=' /file_put/' method='post' enctype=' multipart/form-data'> 2 文件名<input type='file...

珠心算_c语言珠心算-程序员宅基地

珠心算是一种通过在脑中模拟算盘变化来完成快速运算的一种计算技术。珠心算训练,既能够开发智力,又能够为日常生活带来很多便利,因而在很多学校得到普及。某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正整数集合,集合中的数各不相同,然后要求学生回答:其中有多少个数,恰好等于集合中另外两个(不同的)数之和?最近老师出了一些测验题,请你帮忙求出答案。(本题目为2014N..._c语言珠心算

随便推点

程控交换之TST交换网络研究-程序员宅基地

TST交换网络;程控核心交换网络模型。_tst

【熵】熵,KL散度,交叉熵,最大熵模型_如果随机变量x的概率分布为p(x_i),i=1,2,3,\cdots,q,则熵函数h(p)是( )维-程序员宅基地

https://blog.csdn.net/geter_CS/article/details/84572199文章目录熵条件熵最大熵模型熵熵在概率论中是很重要的概念。表示随机变量不确定性的度量。设随机变量 X其概率分布为P(X=xi)=pi,i=1,2...nP(X=x_i)=p_i,i=1,2...nP(X=xi​)=pi​,i=1,2...n,则 X 的熵可以表示为H(p)=−∑i=1n​pi​log(pi​)H(p)=-∑^n_{i=1}​p_i​log(p_i​)H(p)=−∑i=1n​​_如果随机变量x的概率分布为p(x_i),i=1,2,3,\cdots,q,则熵函数h(p)是( )维函

免费馅饼 HDU - 1176 (简单dp)_馅饼 hdu dp-程序员宅基地

Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身_馅饼 hdu dp

冒泡排序学习心得(Java实现)-程序员宅基地

public class arrayDemo05 {public static void main(String args[]){/** 冒泡排序*/int temp;int[] arr={23,12,34,2,67};// for (int i = 0; i // for (int j =0; j // if(arr[j]>=arr[j+1]){// te

相对地址&绝对地址 相对路径&绝对路径_js什么是相对地址?什么是绝对地址?举例说明。-程序员宅基地

相对地址与绝对地址的区别_js什么是相对地址?什么是绝对地址?举例说明。

springboot使用aop实现将日志写入日志文件中_记或往的博客-程序员宅基地

springboot使用aop实现将日志写入日志文件中Why:为什么使用aop实现将日志写入文件中Because: 在做项目中,项目发布后就没有控制台打印了,所以之后如果出现错误都要到日志文件中查看。使用aop可以在无感知的情况下经行日志写入。1.application.properties配置文件#日志配置 //日志写入的文件名logging.file.name=myLogFile.log2.配置aop日志组件类:@Aspect@Componentpublic class LogAs