介绍

  1. 在redux中更好的解决异步操作
  2. redux-saga相当于在redux原来的数据流中多了一层,对action进行监听
  3. 接收到action时,派发一个任务维护state
  4. saga通过Generator方式创建,异步方法同步化

正常redux流程

加入redux-saga之后的流程


使用方式

  1. import { createStore, applyMiddleware } from 'redux'
  2. import createSagaMiddleware from 'redux-saga'
  3. //引入saga文件
  4. import { rootSaga } from './rootSaga'
  5. //使用 redux-saga 模块的 createSagaMiddleware 工厂函数来创建一个 Saga middleware。
  6. //运行 rootSaga 之前,我们必须使用 applyMiddleware 将 middleware 连接至 Store。然后使用
  7. const sagaMiddleware = createSagaMiddleware();
  8. const middlewares = [ sagaMiddleware ];
  9. const store = createStore(rootReducer, applyMiddleware(...middlewares));
  10. sagaMiddleware.run(rootSaga);
  11. 复制代码

redux-saga 辅助函数

sage提供了一些辅助函数,包装了一些内部方法,用来在一些特定的action被发起到store时派生任务

takeEvery

  1. import { call, put } from 'redux-saga/effects'
  2. export function* fetchData(action) {
  3. try {
  4. const data = yield call(Api.fetchUser, action.payload.url);
  5. yield put({type: "FETCH_SUCCEEDED", data});
  6. } catch (error) {
  7. yield put({type: "FETCH_FAILED", error});
  8. }
  9. }
  10. function* watchFetchData() {
  11. yield* takeEvery('FETCH_REQUESTED', fetchData)
  12. }
  13. //有一种用法:监控所有的发起的action
  14. yield takeEvery('*', fn)
  15. 复制代码

takeEvery 允许多个 fetchData 实例同时启动, 在某个特定时刻, 尽管之前还有一个或多个fetchData尚未结束, 我们还是可以启动一个新的fetchData任务-->意思就是只用调用了 FETCH_REQUESTED action的时候就会启动 fetchData 任务.

takeLatest

  1. function* watchFetchData() {
  2. yield* takeLatest('FETCH_REQUESTED', fetchData)
  3. }
  4. 复制代码

在任何时刻 takeLatest只允许一个 fetchData 任务在执行,并且这个任务是最后被启动的那个,如果之前有一个任务再启动的时候执行了fetchData , 那么之前的任务会被自动取消 -- 可以获得最后一次(最新)调用FETCH_REQUESTED action 得到的结果.


Effects

概念

sagas都是Generator函数实现,可以用yield 对 js 对象来表达saga的逻辑,这些对象就是effect,

  1. sagas都是用Generator函数实现的
  2. 在 Generator 函数中,yield 右边的任何表达式都会被求值,结果会被 yield 给调用者
  3. 用yield对Effect(简单对象),进行解释执行
  4. Effect 是一个简单的对象,这个对象包含了一些给 middleware 解释执行的信息。 你可以把 Effect 看作是发送给 middleware 的指令以执行某些操作(调用某些异步函数,发起一个 action 到 store,等等)
  1. //官方例子
  2. import { takeEvery } from 'redux-saga/effects'
  3. import Api from './path/to/api'
  4. //监听如果有一个调用PRODUCTS_REQUESTED 的action的话,就会匹配到第二个参数所代表的effect
  5. function* watchFetchProducts() {
  6. yield takeEvery('PRODUCTS_REQUESTED', fetchProducts)
  7. }
  8. //执行,获取数据
  9. //使用Generator 调用了Api.fetch,在Generator函数中,yield右面的任何表达式都会被求值,结果会被yield给调用者
  10. function* fetchProducts() {
  11. const products = yield Api.fetch('/products')
  12. console.log(products)
  13. }
  14. //第二种方式
  15. import { call } from 'redux-saga/effects'
  16. //call(fn, ...args) 这个函数。与前面的例子不同的是,现在我们不立即执行异步调用,相反,call
  17. //创建了一条描述结果的信息就像在 Redux 里你使用 action 创建器,创建一个将被 Store 执行的、描述 action 的纯文本对象。
  18. //call 创建一个纯文本对象描述函数调用。redux-saga middleware 确保执行函数调用并在响应被 resolve 时恢复 generator
  19. function* fetchProducts() {
  20. const products = yield call(Api.fetch, '/products')
  21. // ...
  22. }
  23. 复制代码

发送action到store

  1. //这种方式是Generator获取到了返回值,在调用dispatch
  2. function* fetchProducts(dispatch)
  3. const products = yield call(Api.fetch, '/products')
  4. dispatch({ type: 'PRODUCTS_RECEIVED', products })
  5. }
  6. import { call, put } from 'redux-saga/effects'
  7. //...
  8. function* fetchProducts() {
  9. const products = yield call(Api.fetch, '/products')
  10. // 创建并 yield 一个 dispatch Effect
  11. yield put({ type: 'PRODUCTS_RECEIVED', products })
  12. }
  13. 复制代码

错误处理


  1. import Api from './path/to/api'
  2. import { call, put } from 'redux-saga/effects'
  3. function* fetchProducts() {
  4. try {
  5. const products = yield call(Api.fetch, '/products')
  6. yield put({ type: 'PRODUCTS_RECEIVED', products })
  7. }
  8. catch(error) {
  9. yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
  10. }
  11. }
  12. 复制代码

使用 try/catch 的方式捕获saga的错误信息


一些概念

从 Saga 内触发异步操作(Side Effect)总是由 yield 一些声明式的 Effect 来完成的 , 一个 Saga 所做的实际上是组合那些所有的 Effect,共同实现所需的控制流。使用上是用yield Effects的方式来完成,Effect包括

  1. call: yield call(Generator, param) yield一个call,命令middleware以参数param调用函数 到Generator,saga等待Generator执行之后,接收返回值继续执行,call是堵塞的,就是等待执行完再继续执行,返回的是执行完正常返回的结果.
  2. take: 是阻塞的,只有监听到他(action.type),才会继续往下执行.也就是说创建一个effect的描述信息,用来命令middleware在Store上等待指定action,在发起与他相匹配的action之前,Generator将暂停.
  3. put: 类似dispatch方法,触发一个action,用来命令middleware向Store发起一个action请求,而且是非阻塞的
  4. fork: 非阻塞的,遇到它不需要等待他执行完毕,就可以继续往下执行,fork返回的是一个任务,可以被取消
  5. cancel: 针对fork方法返回的任务,进行取消
  6. select: 可以从全局state中获取状态
  7. saga: 就是用* 注册的函数,一个函数就是一个saga
  8. effect: 上面的call,put,take...就是effect
  1. function* watchAndLog() {
  2. while (true) {
  3. const action = yield take('*')
  4. const state = yield select()
  5. }
  6. }
  7. take,它将会暂停 Generator 直到一个匹配的 action 被发起了,watchAndLog 处于暂停状态,直到任意的一个 action 被发起。
  8. 复制代码

无阻塞调用-fork

fork一个任务,任务会在后台启动,调用者也可以继续它的流程,而不用等待被fork的任务执行结束 当我们需要有并发操作的时候,使用call effect会阻塞saga的执行,使用fork就需要关心被阻塞,或者等待结果返回在继续执行

  1. const result = yield fork (saga,param)
  2. 复制代码

同时执行多个任务

  1. const [users, repos] = yield [
  2. call(fetch, '/users'),
  3. call(fetch, '/repos')
  4. ]
  5. 复制代码

当需要同步执行多个任务,需要把yield一个包含了effect的数组,Generator将会阻塞,等所有的effect都执行完毕


使用

  1. //redux.connect所需要绑定到props上的action
  2. function mapDispatchToProps(dispatch) {
  3. return {
  4. getHome: bindActionCreators(getHomeAdData, dispatch)
  5. }
  6. }
  7. //一个 action creator
  8. export function getHomeAdData(){
  9. return {
  10. type: actionTypes.HOME_AD_DATA,
  11. }
  12. }
  13. //监听action.type,然后出发后面的action
  14. export default function* rootSaga () {
  15. // 就在这个rootSaga里面利用takeEvery去监听action的type
  16. yield takeEvery('HOME_AD_DATA', getHomeAdData);
  17. yield takeEvery('GET_LIKE_LIST_DATA', getLikeListData);
  18. }
  19. //通过yield call Effect 获取返回值,继续下面操作
  20. export function* getHomeAdData() {
  21. let data = yield call(getAdData)
  22. ...
  23. yield put({type:UPDATE_HOME_AD_DATA, data: dataArr})
  24. }
  25. export function getAdData() {
  26. const result = axios.get('/api/homead')
  27. return result
  28. }
  29. 复制代码
  30.  
  31. https://juejin.im/post/5b306e6151882574d3249605

Redux-saga-整理的更多相关文章

  1. Redux----Regular的Redux实现整理

      Regular的Redux实现整理 什么问题? 组件的树形结构决定了数据的流向,导致的数据传递黑洞 怎么解决? 所有组件都通过中介者传递共享数据 方案: 中介者: (function create ...

  2. [React] 14 - Redux: Redux Saga

    Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga  [入门] Ref: 从redux-thun ...

  3. react系列(六)Redux Saga

    在Redux中常要管理异步操作,目前社区流行的有Redux-Saga.Redux-thunk等.在管理复杂应用时,推荐使用Redux-Saga,它提供了用 generator 书写类同步代码的能力. ...

  4. react native redux saga增加日志功能

    redux-logger地址:https://github.com/evgenyrodionov/redux-logger 目前Reac native项目中已经使用redux功能,异步中间件使用red ...

  5. redux 个人整理

    序 本人工作之余的闲暇时间还是很充裕的.在完成经理安排的任务后,基本上都是在自学,主要是阅读各种技术文档.浏览博客.运行别人写的一些前端demo并观赏与赞叹.在ScorpionJay 同学的带领下,我 ...

  6. redux+saga+reducer

    saga.js这个文件里面的函数实际没有在其他jsx中引用吧?这个文件的作用就是把异步数据拿到,放进reducer,如果jsx想取,需要结合connect来取数据.

  7. redux saga学习

    来源地址:https://www.youtube.com/watch?v=o3A9EvMspig Saga的基本写法 takeEvery与takeLatest的区别 takeEvery是指响应每一个请 ...

  8. [转] How to dispatch a Redux action with a timeout?

    How to dispatch a Redux action with a timeout? Q I have an action that updates notification state of ...

  9. [Full-stack] 状态管理技巧 - Redux

    资源一: In React JS Tutorials, lectures from 9. From: React高级篇(一)从Flux到Redux,react-redux 从Flux到Redux,再到 ...

  10. Redux生态系统

    生态系统 Redux 是一个体小精悍的库,但它相关的内容和 API 都是精挑细选的,足以衍生出丰富的工具集和可扩展的生态系统. 如果需要关于 Redux 所有内容的列表,推荐移步至 Awesome R ...

随机推荐

  1. Vue--运行项目发送http://localhost:8080/sockjs-node/info请求报错,造成浏览器不能热更新

    今早习惯打开vscode 输入 npm run dev 准备修复测试提出的bug 不料一堆通红的报错,让人感到有点绿的慌. 有问题呢,就需要解决问题.经过一番排查后发现是我昨天为了让测试在我本地项目中 ...

  2. Linux查看系统当前登录用户的命令,top命令看到users有多个用户登录

    Linux查看系统当前登录用户的命令,top命令看到users有多个用户登录 作为系统管理员,top命令看到users有多个用户登录,会需要查看下是否被黑客进入了. 实战例子:top命令:top - ...

  3. filebeat + ELK 部署篇

    ELK Stack Elasticsearch:分布式搜索和分析引擎,具有高可伸缩.高可靠和易管理等特点.基于 Apache Lucene 构建,能对大容量的数据进行接近实时的存储.搜索和分析操作.通 ...

  4. Modbus协议 CRC 校验码

    CRC(循环冗余校验)在线计算 http://www.ip33.com/crc.html 里面的8005的多项式值,但网上看到的算法都是用A001来异或的 ---------------------- ...

  5. CentOS用yum安装MySQL 8.0 .

    先说一句,fuck,搞了一下午. 步骤:一:安装yum源: 1.wget https://dev.mysql.com/get/mysql80-community-release-el6-3.noarc ...

  6. pm2入门

    简介 PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控.自动重启.负载均衡等,而且使用非常简单. 安装 全局安装,简直不能更简单. npm install -g ...

  7. springboot测试启动报错java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

    springboot测试启动报错: java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you ne ...

  8. Mysql 数据库部署(解压免安装)

    下载压缩包,解压. 在根目录下添加my.ini, 复制一下内容,保存. [mysqld] skip-grant-tables #绑定IPv4和3306端口 bind-address = 0.0.0.0 ...

  9. LVS(二):四种工作模型

    面试的时候必问这个四种工作模式,因为这几乎是企业里面必用的内容,所以一定要将其理解通透. 一.lvs-nat模式 二.LVS-DR模式(默认) 三.LVS-tun模式 四.LVS-fullnat模式 ...

  10. 201871010118-唐敬博《面向对象程序设计(java)》第十六周学习总结

    博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 <https://www.cnblogs.com/nwnu-daizh/> 这个作业的要求在哪里 <https://ww ...