介绍

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

正常redux流程

加入redux-saga之后的流程


使用方式

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

redux-saga 辅助函数

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

takeEvery

import { call, put } from 'redux-saga/effects'
export function* fetchData(action) {
try {
const data = yield call(Api.fetchUser, action.payload.url);
yield put({type: "FETCH_SUCCEEDED", data});
} catch (error) {
yield put({type: "FETCH_FAILED", error});
}
} function* watchFetchData() {
yield* takeEvery('FETCH_REQUESTED', fetchData)
} //有一种用法:监控所有的发起的action
yield takeEvery('*', fn)
复制代码

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

takeLatest

function* watchFetchData() {
yield* takeLatest('FETCH_REQUESTED', fetchData)
}
复制代码

在任何时刻 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,等等)
//官方例子
import { takeEvery } from 'redux-saga/effects'
import Api from './path/to/api' //监听如果有一个调用PRODUCTS_REQUESTED 的action的话,就会匹配到第二个参数所代表的effect
function* watchFetchProducts() {
yield takeEvery('PRODUCTS_REQUESTED', fetchProducts)
}
//执行,获取数据
//使用Generator 调用了Api.fetch,在Generator函数中,yield右面的任何表达式都会被求值,结果会被yield给调用者
function* fetchProducts() {
const products = yield Api.fetch('/products')
console.log(products)
} //第二种方式
import { call } from 'redux-saga/effects'
//call(fn, ...args) 这个函数。与前面的例子不同的是,现在我们不立即执行异步调用,相反,call
//创建了一条描述结果的信息就像在 Redux 里你使用 action 创建器,创建一个将被 Store 执行的、描述 action 的纯文本对象。
//call 创建一个纯文本对象描述函数调用。redux-saga middleware 确保执行函数调用并在响应被 resolve 时恢复 generator
function* fetchProducts() {
const products = yield call(Api.fetch, '/products')
// ...
} 复制代码

发送action到store

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

错误处理


import Api from './path/to/api'
import { call, put } from 'redux-saga/effects' function* fetchProducts() {
try {
const products = yield call(Api.fetch, '/products')
yield put({ type: 'PRODUCTS_RECEIVED', products })
}
catch(error) {
yield put({ type: 'PRODUCTS_REQUEST_FAILED', error })
}
} 复制代码

使用 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
function* watchAndLog() {
while (true) {
const action = yield take('*')
const state = yield select()
}
}
take,它将会暂停 Generator 直到一个匹配的 action 被发起了,watchAndLog 处于暂停状态,直到任意的一个 action 被发起。 复制代码

无阻塞调用-fork

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

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

同时执行多个任务

const [users, repos] = yield [
call(fetch, '/users'),
call(fetch, '/repos')
]
复制代码

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


使用

//redux.connect所需要绑定到props上的action
function mapDispatchToProps(dispatch) {
return {
getHome: bindActionCreators(getHomeAdData, dispatch)
}
}
//一个 action creator
export function getHomeAdData(){
return {
type: actionTypes.HOME_AD_DATA,
}
}
//监听action.type,然后出发后面的action
export default function* rootSaga () {
// 就在这个rootSaga里面利用takeEvery去监听action的type
yield takeEvery('HOME_AD_DATA', getHomeAdData);
yield takeEvery('GET_LIKE_LIST_DATA', getLikeListData);
}
//通过yield call Effect 获取返回值,继续下面操作
export function* getHomeAdData() {
let data = yield call(getAdData)
...
yield put({type:UPDATE_HOME_AD_DATA, data: dataArr})
} export function getAdData() {
const result = axios.get('/api/homead')
return result
}
复制代码
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-cli3脚手架工具快速创建一个项目

    1.首先全局安装一下vue-cli3 npm install -g @vue/cli 或 yarn global add @vue/cli vue -V查看版本(这里注意V是大写哦) 2.vue cr ...

  2. SQL行转列,列转行

    SQL 行转列,列转行 行列转换在做报表分析时还是经常会遇到的,今天就说一下如何实现行列转换吧. 行列转换就是如下图所示两种展示形式的互相转换 行转列 假如我们有下表: SELECT * FROM s ...

  3. 数据库系统(五)---MySQL基础

    一.SQL基本概念: SQL 已经成为关系数据库的标准语言,是一种数据库查询和程序设计语言,用 于存取数据以及查询.更新和管理关系数据库系统. 功能不仅仅是查询,还包括数据定义.数据操纵和数据控制等于 ...

  4. JMETER 计数器的表现

    1.计数器在线程中表现(虚拟用户). 线程组使用4个线程即4个虚拟用户. 如果不勾选每用户独立跟踪计数器. 那么这个计数器将会累加4次. 计算结果为7. 勾选的情况. 这里我们可以看到 index 一 ...

  5. 关于苹果macOS更新到Catalina后出现的各种问题(持续更新)

    一.Mac系统更新后 Git 不能用,提示 missing xcrun at:xxx xcrun: error: invalid active developer path (/Library/Dev ...

  6. 01day-微信小程序 表单组件 动态绑定变量 导航组件 地图组件 view text button 上下滚动组件

    04-开发者环境搭建(下载安装开发者工具) 01==>微信开发工具的下载 安装 微信小程序的工具是 下载稳定版本的 安装的时候 直接下一步就可以了 02==>项目名陈随便输入 目录 App ...

  7. Window包管理工具scoop

    自定义安装路径安装 scoop安装应用路径 目标目录是D:\Program Files\Scoop,在PowerShell命令控制台中运行: [environment]::setEnvironment ...

  8. 【Spring AOP】通知(五)

    一.通知介绍 1. 前置通知(Before) 在目标方法执行之前执行的通知. 前置通知方法,可以没有参数,也可以额外接收一个JoinPoint,Spring会自动将该对象传入,代表当前的连接点,通过该 ...

  9. 配置好运行后Error creating context 'spring.root': Could not load type from string value

    在Webconfig文件的当前项目下引用相关项目

  10. Codeforces Round #545 (Div. 2) E 强连通块 + dag上求最大路径 + 将状态看成点建图

    https://codeforces.com/contest/1138/problem/E 题意 有n个城市(1e5),有m条单向边(1e5),每一周有d天(50),对于每个城市假如在某一天为1表示这 ...