回顾

  • 初识react(一) 揭开jsx语法和虚拟DOM面纱
  • 初识react(二) 实现一个简版的html redux.js的demo
  • 初识react(三)在 react中使用redux来实现简版计数器
  • 初识react(四) react中异步解决方案之 redux-saga
  • 初识react(五) 数据流终极解决方案 dva(零配置)

今天demo是实现一个异步的计算器,探究redux-saga工作流程

简介

  • redux-saga 是一个 redux 的中间件,而中间件的作用是为 redux 提供额外的功能。
  • 由于在 reducers 中的所有操作都是同步的并且是纯粹的,即 reducer 都是纯函数,纯函数是指一个函数的返回结果只依赖于它的参数,并且在执行过程中不会对外部产生副作用,即给它传什么,就吐出什么。
  • 但是在实际的应用开发中,我们希望做一些异步的(如Ajax请求)且不纯粹的操作(如改变外部的状态),这些在函数式编程范式中被称为“副作用”。

redux-saga 就是用来处理上述副作用(异步任务)的一个中间件。它是一个接收事件,并可能触发新事件的过程管理者,为你的应用管理复杂的流程。

redux-saga工作原理

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

redux-saga分类

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

基本介绍已经讲完了,当做完一个demo后,回头再看redux-saga官网或者上面讲解,可能会有更深的体会

使用redux-saga实现一个异步计数器

由于目录结构跟上篇文章一样,在这里就只把变动的部分单独抽离出来讲解

  • 先回顾下初识react(三)在 react中使用redux来实现简版计数器

1、修改actions/counter.js

  • 增加一个异步记数的动作类型。
import * as Types from "../action-types";
let actions ={add(num){return{type:Types.INCREMENT,count:num}},minus(num){return{type:Types.DECREMENT,count:num}},//增加了一个异步记数的类型,用于在counter.js中派发动作async(num){return {type:Types.ADD_ASYNC}}
};
export default actions;

2、重点,在src目录下增加saga.js文件

//takeEvery=>负责监听  put=>派发动作   call=>告诉saga,执行delay,并传入1000作为参数
import {takeEvery,put,call} from "redux-saga/effects";
import * as Types from "./store/action-types";
const delay = ms=>new Promise((resolve,reject)=>{setTimeout(()=>{resolve()},ms)
})
//saga分为三类 1、rootsaga 2、监听saga 3、worker干活的saga
function* add() {yield call(delay,1000);//就是指挥saga中间件向仓库派发动作yield put({type:Types.INCREMENT,count:10});
}
function* watchAdd() {//监听派发给仓库的动作,如果动作类型匹配的话,会执行对应的监听生成器yield takeEvery(Types.ADD_ASYNC,add)
}
export default function* rootSaga() {yield watchAdd()}

还记得上面说的,rudux-saga分类,root saga ->watcher saga -> worker saga。在这段代码中将会体现,代码我们从上往下看。

2.1 saga工作流程(代码从下往上看)
  • 默认导出了rootSaga,即saga的入口文件
  • watcher saga ->wactchAdd 负责监听派发的动作,如果动作类型匹配,执行对应的 worker saga
  • 上面的worker saga指代的是 add函数
2.2 redux-saga/effects 副作用

在实际的应用开发中,我们希望做一些异步的(如Ajax请求)且不纯粹的操作(如改变外部的状态),这些在函数式编程范式中被称为“副作用”。

  • takeEvery=>负责监听,监听派发给仓库的动作,如果动作类型匹配的话,会执行对应的监听生成器->add
  • put=>派发动作,可以理解为dispatch
  • call=>告诉saga,执行delay函数,并把参数传过去。注意: delay函数必须返回promise

讲到这里,流程就说完了,接下来在store中执行rootSaga

3、在store/index引入rootSaga

    import {createStore,applyMiddleware} from 'redux';import createSagaMiddleware from "redux-saga"; //引入redux-sagaimport  rootSaga from "../saga" //引入我们上面写好的rootSagaimport reducer from "./reducers"let sagaMiddleware =createSagaMiddleware(); //执行得到saga中间件let store = createStore(reducer,applyMiddleware(sagaMiddleware)); //使用中间件sagaMiddleware.run(rootSaga); //开始执行rootSagaexport  default  store;

对于redux中间件没有讲解,这部分内容涉及东西比较多,也不太好理解,写这个react系列目的是尽可能简单的让所有人理解,想看所有的redux源码解析,底部会留下所有总结的代码仓库。

4、在counter.js组件中派发这个异步动作

  • 代码跟上篇文章一模一样,只是增加了按钮实现异步操作
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {connect} from "react-redux";
import actions from "../store/actions/counter"
class Counter extends Component {render() {console.log(this.props);return(<div><h1>{this.props.number}</h1><button onClick={()=>{this.props.add(5)}}> </button><button onClick={()=>{this.props.minus(1)}}>-</button>//增加异步操作<button onClick={()=>{this.props.async()}}>异步加10</button></div>)}
}
export default connect(state=>({...state
}),actions)(Counter)

终结,看效果。可以看出,点击后等待1s才加10。那我们就可以在call()中传入执行的异步函数(如ajax)来获取数据啦。我们这个例对应的delay函数


最后在梳理下整个过程

  • 1、组件中调用了this.props.async(),返回的action对象=>{type:Types.ADD_ASYNC}会在connect方法中被派发

  • 2、saga中takeEvery(Types.ADD_ASYNC,add),监听到动作的类型后,触发 worker saga =>add

  • 3、worker saga中先 yield call(delay,1000); 执行delay方法,延时1s

  • 4、yield put({type:Types.INCREMENT,count:10}); 最后派发的还是INCREMENT的类型

  • 5、接着被reducer处理,更新state

  • 6、页面刷新

  • 更多优质文章参考

  • redux所有源码解析戳这里

初识react(四) react中异步解决方案之 redux-saga相关推荐

  1. 如何在React Native中使用Redux Saga监视网络更改

    by Pritish Vaidya 通过Pritish Vaidya 如何在React Native中使用Redux Saga监视网络更改 (How to monitor network change ...

  2. [译] How to NOT React:React 中常见的反模式与陷阱

    原文地址:How to NOT React: Common Anti-Patterns and Gotchas in React 原文作者:NeONBRAND 译文出自:掘金翻译计划 本文永久链接:g ...

  3. React项目开发中的数据管理

    原文链接:https://blog.csdn.net/hl582567508/article/details/76982756 redux中文文档:http://cn.redux.js.org/ Re ...

  4. react 交互_如何在React应用程序中跟踪用户交互

    react 交互 by Faouzi Oudouh 通过Faouzi Oudouh 如何在React应用程序中跟踪用户交互 (How to track user interactions in you ...

  5. React Native工程中TSLint静态检查工具的探索之路

    背景 建立的代码规范没人遵守,项目中遍地风格迥异的代码,你会不会抓狂? 通过测试用例的程序还会出现Bug,而原因仅仅是自己犯下的低级错误,你会不会抓狂? 某种代码写法存在问题导致崩溃时,只能全工程检查 ...

  6. 如何简化React应用程序中的状态-轻松实现Redux

    by Arnel Enero 通过Arnel Enero 如何简化React应用程序中的状态-轻松实现Redux (How to simplify state in your React app - ...

  7. React基础-React中发送Ajax请求以及Mock数据

    前言 在 React 中, render 函数返回的结果,取决于组件的 props 和 state 我们都知道 UI 页面上的数据不是写死的,往往是从后端的数据接口中拿到的 然后将真实的数据填充到页面 ...

  8. react打包后图片丢失_React系列四 - React脚手架

    一. 认识脚手架 1.1. 前端工程的复杂化 如果我们只是开发几个小的demo程序,那么永远不需要考虑一些复杂的问题: 比如目录结构如何组织划分: 比如如何管理文件之间的相互依赖: 比如如何管理第三方 ...

  9. React组件方法中为什么要绑定this

    React组件方法中为什么要绑定this 如果你尝试使用过React进行前端开发,一定见过下面这样的代码: //假想定义一个ToggleButton开关组件class ToggleButton ext ...

最新文章

  1. 掌握Node.js中的Async和Await
  2. Oracle数据库相关
  3. Java在一个文件中匹配字符串
  4. Vim安装、配置和插件的添加使用(可以以目录的形式打开)
  5. c++ vector注意事项
  6. 10个可以简化开发过程的MySQL工具
  7. Qt 如何处理密集型耗时的事情
  8. spark任务shell运行_大数据系列:Spark的工作原理及架构
  9. oracle异机恢复 open resetlogs 报:ORA-00392
  10. 五分钟实现网站安全 创新工场“安全宝”吸引大量用户
  11. 《LUA游戏开发实践指南》学习笔记1
  12. 交际过程的两个基本环节_要客品味 | 人际交往礼仪——交际礼仪的基本原则
  13. html select ajax,AJAX 动态加载后台数据 绑定select的方法
  14. java 弹弹堂源码_弹弹堂s应用宝版下载
  15. VS2013+简单稀疏光束调整库SSBA配置(64位编译)
  16. 李宏毅2022机器学习HW4解析
  17. 照片损坏怎么办,怎么恢复受损照片
  18. html元素相对定位和绝对定位
  19. 主板方面带杜比是什么意思_什么是杜比维度耳机?
  20. 用 TFserving 部署深度学习模型

热门文章

  1. 7.5 GRASP原则五:高内聚 High Cohesion
  2. SpringAOP02 自定义注解
  3. CentOS7桌面版系统使用的一些小技巧
  4. 牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) H.Tree Recovery-完全版线段树(区间更新、区间求和)...
  5. 2. python 参数个数可变的函数
  6. ARM的编程模式和7种模式
  7. oracle instr查询字符串
  8. C++ 类成员引用变量的使用
  9. python辅助脚本教程_微信跳一跳python辅助脚本实例分享
  10. 让程序结果在屏幕上暂停一段时间