github : https://github.com/redux-saga/redux-saga

文档:https://redux-saga.js.org/

redux-saga:  redux中间件,旨在处理应用中的副作用

使用:

import createSagaMiddleware from 'redux-saga'
import {createStore,applyMiddleware} from 'redux' const saga = createSagaMiddleware(); const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(mysagas);
  

 

基础概念:

  saga-middleware 检查每个被 yield 的 Effect 的类型,然后决定如何实现哪个 Effect。如果 Effect 类型是 PUT 那 middleware 会 dispatch 一个 action 到 Store。 如果 Effect 类型是 CALL 那么它会调用给定的函数。

put({type: 'INCREMENT'}) // => { PUT: {type: 'INCREMENT'} }
call(delay, 1000) // => { CALL: {fn: delay, args: [1000]}}

辅助函数:

  takeEvery : 可以同时启动多次任务

  takeLatest : 在一次任务未完成之前,遇到新任务将取消之前任务。

声明式的effect

  call:  saga通过 Generator函数实现,在yield函数后执行effect,其中call是用于执行某些异步操作的。

yield requestSome('/xxx');

yield call(requestSome,'/xxx')
//之所以用call取代上面的直接调用写法,好处在于,
//编写测试代码的时候,可以deepEqual generator函数的next().value和call(requestSome,'/xxx'),这样所有的effect都可以被测试,而不需要mock yield后的执行结果

dispatching actions:

  put : 和上面的call一样,中间件提供put 来把action丢到中间件中去dispatch,好处同样是便于测试

高级:

take:

  call方法可以yield一个promise,然后会阻塞generator的执行,知道promise resolve,结果返回
  take(xxx)同理,阻塞generator直到xxx匹配的action被触发

  由此:take(*)可以用于抓取log,take(*)会匹配任意的action触发事件

  使用while(true){ take(/xxx/) }  可以创建持续的action监听,当然也可以根据需求,选择性的监听,只需改版while(xxx)的条件就行了

function* actionLog(){
while(true){
yield take('INCREMENT');
console.log('do increment');
yield take('DECREMENT');
console.log('do decrement')
}
}
//take可以控制action的监听顺序,如上,会先监听到INCREMENT之后,才会再往下监听DECREMENT,完后继续监听INCREMENT。这在一些顺序明确的action事件里,可以将流程代码写在一起,
//如login logout

fork:

  fork和take不同,take会和call一样阻塞代码的执行,知道结果返回,fork则不会,它会将任务启动并且不阻塞代码的执行,

  fork会返回一个task,可以用cacel(task)来取消任务

  https://redux-saga.js.org/docs/advanced/NonBlockingCalls.html

  此文中将login 和logout作为例子,在login请求未返回来之前执行了logout,则需要cacel未完成的login,又不能用take(login)否则阻塞logout,会在login响应之前take不到logout。

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

// ...

function* loginFlow() {
while (true) {
const {user, password} = yield take('LOGIN_REQUEST')
// fork return a Task object
const task = yield fork(authorize, user, password)
const action = yield take(['LOGOUT', 'LOGIN_ERROR'])
if (action.type === 'LOGOUT')
yield cancel(task)
yield call(Api.clearItem, 'token')
}
} import { take, call, put, cancelled } 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})
yield call(Api.storeItem, {token})
return token
} catch(error) {
yield put({type: 'LOGIN_ERROR', error})
} finally {
if (yield cancelled()) {
// ... put special cancellation handling code here
}
}
}

all:

  yield表达式,可以将语句分段执行,但如果有时候想同时执行两个任务,则需要用到all

import {all,call} from 'redux-saga/effect'

//此处会同步执行两个call的任务
const [users, repos] = yield all([
call(fetch, '/users'),
call(fetch, '/repos')
])

race:

  和promise中的race一个概念,执行多个任务,受到响应后则继续执行  

function* fetchPostsWithTimeout() {
const {posts, timeout} = yield race({
posts: call(fetchApi, '/posts'),
timeout: call(delay, 1000)
}) if (posts)
put({type: 'POSTS_RECEIVED', posts})
else
put({type: 'TIMEOUT_ERROR'})
}

yield *

  通过yield * xxx()来组合多个generator任务。

组合saga:

  可以通过yield [call(task1),call(task2)...]来组合多个generator。

channels:

throttle:

  节流

delay:

  防抖动

react系列笔记:第三记-redux-saga的更多相关文章

  1. react系列笔记:第一记-redux

    前言: 目前公司使用dva,对于前不久还是使用原生js的我来说,花了差不多一两周时间,基本掌握如何使用.虽然对于react有一点点基础,但很多地方未深入,很多概念也很模糊,故从本文开始,记录一下系统的 ...

  2. react系列笔记:第二记-中间件

    中间件所做的事情就是在action发起后,到reducer之前做扩展,实现的方式是对store的dispatch进行包装 store.dispatch => [middlewales] => ...

  3. react系列笔记1 用npx npm命令创建react app

    react系列笔记1 用npx npm命令创建react app create-react-app my-app是开始构建新的 React 单页应用程序的最佳方式.它已经为你设置好了开发环境,以便您可 ...

  4. [angularjs] angularjs系列笔记(三)模型

    ng-model指令 ng-model可以将输入域的值与AngularJs的变量绑定 双向绑定 当修改输入域的值时候,AngularJs属性的值也将修改 <div ng-app="Ho ...

  5. PHP多进程系列笔记(三)

    本节讲解几个多进程的实例. 多进程实例 Master-Worker结构 下面例子实现了简单的多进程管理: 支持设置最大子进程数 Master-Worker结构:Worker挂掉,Master进程会重新 ...

  6. react系列教程

    这个系列将从基础语法讲起,把react全家桶都讲到,然后到具体的使用,最后完成后,会写一个完整的demo. 前置要求: 基本的CSS,JS要熟练. 部分ES6语法需要了解.可以参考下面提到的阮一峰老师 ...

  7. React学习笔记 - 组件&Props

    React Learn Note 4 React学习笔记(四) 标签(空格分隔): React JavaScript 三.组件&Props 组件可以将UI切分成一些独立的.可复用的部件,这样你 ...

  8. React学习笔记 - 元素渲染

    React Learn Note 3 React学习笔记(三) 标签(空格分隔): React JavaScript 二.元素渲染 元素是构成react应用的最小单位. 元素是普通的对象. 元素是构成 ...

  9. React学习笔记 - JSX简介

    React Learn Note 2 React学习笔记(二) 标签(空格分隔): React JavaScript 一.JSX简介 像const element = <h1>Hello ...

随机推荐

  1. Python3 tkinter基础 Spinbox 可输入 能调整的 从指定范围内选择参数的控件

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  2. HTML与CSS的一些知识(二)

    续: 5.表单标签<form></form> 用于收集用户信息,统一提交到服务器 一般用input标签收集,再用提交按钮提交:input标签根据type属性值不同有不同的类型: ...

  3. 【Git】Git使用记录: remove *.lock eg: index.lock/head.lock

    问题 Another git process seems to be running in this repository, e.g. an editor opened by 'git commit' ...

  4. Unable to start Ocelot because either a ReRoute or GlobalConfiguration

    在ASP.Net Core项目APIGateway中添加Ocelot+Consul然后运行时 ,VS2017报如下错 : 内部异常 1: Exception: Unable to start Ocel ...

  5. GIT导出差异版本更新的文件列表

    之前写了一篇SVN导出差异版本更新的文件列表 这次写git如何导出差异化版本文件列表 查找了一番,发现git diff这个命令 $ git diff 2da595c daea1d6 --name-on ...

  6. 决策树算法原理(CART分类树)

    决策树算法原理(ID3,C4.5) CART回归树 决策树的剪枝 在决策树算法原理(ID3,C4.5)中,提到C4.5的不足,比如模型是用较为复杂的熵来度量,使用了相对较为复杂的多叉树,只能处理分类不 ...

  7. APScheduler——定时任务框架

    https://www.cnblogs.com/luxiaojun/p/6567132.html

  8. HTML标记

    html:超文本标记语言 标记,标签,元素 单标签:<标签名  属性名="属性值" 属性名=“属性值” /> 双标签:<标签名  属性名="属性值” 属 ...

  9. 又谈T检验

    今天有同学的论文被指摘了,就是又用了T检验,又用了ANOVA,reviewer直接说用ANOVA就行了.所以回想下了T检验. 简而言之,T检验就是用来比较均值的,样本均值和已知总体均值是否有差异.(也 ...

  10. Abstract与Virtual

    转自 http://www.cnblogs.com/wang7/archive/2012/04/17/2453624.html virtual和abstract都是用来修饰父类的,通过覆盖父类的定义, ...