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. jieba库和好玩的词云

    首先,通过pip3 install jieba安装jieba库,随后在网上下载<斗破>. 代码如下: import jieba.analyse path = '小说路径' fp = ope ...

  2. Redis 错误:Failed with result 'start-limit-hit'

    Redis 错误:Failed with result 'start-limit-hit' 背景 Redis 版本为 5.0.4: 文件 /etc/systemd/system/redis.servi ...

  3. python on sql

    USE [DemoDb]GOexecute sp_execute_external_script @language = N'Python', @script = N'a = 1b = 2c = a/ ...

  4. PHP工程师必备知识整理

    一.http/https协议,tcp/ip协议,websocket,session,cookie 二.php:oop,thinkphp5,laravel 三.mysql.memcache.redis ...

  5. Error: EACCES: permission denied, mkdir '......node-sass/build'错误解决方案

    安装node-sass时出现一下错误: gyp ERR! configure error gyp ERR! stack Error: EACCES: permission denied, mkdir ...

  6. c++_day5_成员指针

    1.成员指针实质:特定成员变量在对象实例中的相对地址. 2.类内可以直接初始化静态常量(声明部分).

  7. git1使用步骤初始化拉取修改提交推送

    Git 使用 git init 命令来初始化一个 Git 仓库,Git 的很多命令都需要在 Git 的仓库中运行,所以 git init 是使用 Git 的第一个命令. 在执行完成 git init  ...

  8. leecode第二百三十一题(2的幂)

    class Solution { public: bool isPowerOfTwo(int n) { bool is_flag=false; ) { ==)//如果为1,看是不是第一个1 { if( ...

  9. HDU 1257 最少拦截系统(思路题)

    Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高 ...

  10. list内含有元组或字典

    a=[(")] for k,v,i in a: print(k,v,i) 结果: 1 21 12 2 31 32 list里含元组,可以用这种遍历输出挨个元素 但list里含字典时,这样就只 ...