Redux-saga官方文档知识点记录基础部分

整理和总结官方文档的中文翻译版上面对于Redux-sage的介绍
文档地址:http://leonshi.com/redux-saga-in-chinese/index.html

概述

redux-saga 是一个用于管理Redux 应用异步操作的中间件(又称异步 action)。 redux-saga 通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替 redux-thunk中间件。
   Sagas 只会在应用启动时调用。 Sagas 可以被看作是在后台运行的进程。Sagas 监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其 他的 action 到 Store,甚至是调用其他的 Sagas。
   在 redux-saga 的世界里,所有的任务都通用 yield Effects 来完成(译注:Effect 可以看作是 redux-saga 的任务单元)。Effects 都是简单的 Javascript 对象,包含了要被 Saga middleware 执行的信息(打个比方,你可以看到 Redux action 其实是一个个包含执行信息的对象)
   因为使用了 Generator,redux-saga让你可以用同步的方式写异步代码

基本概念

1 Saga 辅助函数

takeEvery :允许多个 fetchData实例同时启动。在某个特定时刻,我们可以启动一个新的 fetchData任务, 尽管之前还有一个或多个 fetchData尚未结束。
   takeLatest:只允许执行一个 fetchData任务。并且这个任务是最后被启动的那个。 如果之前已经有一个任务在执行,那之前的这个任务会自动被取消。
例子:

import { takeEvery } from 'redux-saga'
function* watchFetchData() {
    yield* takeEvery('FETCH_REQUESTED', fetchData)
}```
   监听 FETCH_REQUESTED action 之后执行下面的异步action 任务

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});
}
}

#####2 声明式 Effects
   我们从 Generator 里 yield 纯 JavaScript 对象以表达 Saga 逻辑。 我们称呼那些对象为 *Effect*。Effect 是一个简单的对象,这个对象包含了一些给 middleware 解释执行的信息。 你可以把 Effect 看作是发送给 middleware 的指令以执行某些操作(调用某些异步函数,发起一个 action 到 store)。
   一个 Saga 所做的实际上是组合那些所有的 Effect,共同实现所需的控制流。 最简单的是只需把 yield 一个接一个地放置,就可对 yield 过的 Effect 进行排序。
   我们已经看到,使用 Effect 诸如 call 和 put,与高阶 API 如 takeEvery相结合,让我们实现与redux-thunk 同样的东西, 但又有额外的易于测试的好处。
######2.1 Effect 概念是如何让 Sagas 很容易地被测试的
   假设我们有一个监听 PRODUCTS_REQUESTED action 的Saga。每次匹配到 action,它会启动一个从服务器上获取产品列表的任务。
   现在要对这段逻辑编写测试, 在测试过程中,执行真正的服务是一个既不可行也不实用的方法,所以我们必须 模拟函数。也就是说,我们需要将真实的函数替换为一个假的,这个假的函数并不会真的发送 AJAX 请求而只会检查是否使用正确的参数调用方法。模拟使测试更加困难和不可靠。
   实际上对这段逻辑的测试我们需要的只是保证任务 yield 一个正确的函数,并且这个函数有着正确的参数。  **我们可以仅仅 yield 一条描述函数调用的信息** 
   实际中当yield 一个方法时,可以使用call(fn, ...args)这个函数,**call创建了一条描述结果的信息**,call 只是一个返回纯文本对象的函数,redux-saga middleware 确保执行函数调用并在响应被 resolve 时恢复 generator。
代码示例

import { takeEvery } from 'redux-saga'
import Api from './path/to/api'
function* watchFetchProduts() {
yield* takeEvery('PRODUCTS_REQUESTED',fetchProducts)
}
function* fetchProducts() {
const products = yield call(Api.fetch, '/products')
}

//测试代码
import { call } from 'redux-saga/effects'
import Api from '...'
const iterator = fetchProducts()
assert.deepEqual(
iterator.next().value, call(Api.fetch, '/products')

#####3 发起 action 到 store
   我们想发起一些action通知   
   dispatch({type:'PRODUCTS_RECEIVED', products })
           为了编写方便测试的代码,使用Effect的概念,使用指令的方式来发起通话,**只需创建一个对象来指示 middleware 我们需要发起一些 action,然后让 middleware 执行真实的 dispatch。**这种方式我们就可以同样的方式测试 Generator 的 dispatch:只需检查 yield 后的 Effect,并确保它包含正确的指令。指令为put
代码示例

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 { call, put } from 'redux-saga/effects'
import Api from '...'
const iterator = fetchProducts()
// 期望一个 call 指令
assert.deepEqual(
iterator.next().value, call(Api.fetch, '/products'),
"fetchProducts should yield an Effect call(Api.fetch,'./products')"
)
// 创建一个假的响应对象
const products = {}
// 期望一个 dispatch 指令
assert.deepEqual(
iterator.next(products).value, put({ type:'PRODUCTS_RECEIVED', products }),

   "fetchProducts should yield an Effect put({ type: 'PRODUCTS_RECEIVED', products })"

)

#####4 错误处理
   我们可以使用熟悉的 try/catch语法在 Saga 中捕获错误。
代码示例

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 })
}
}
//测试代码
import { call, put } from 'redux-saga/effects'
import Api from '...'
const iterator = fetchProducts()
// 期望一个 call 指令
assert.deepEqual(
iterator.next().value, call(Api.fetch, '/products'), "fetchProducts should yield an Effect call(Api.fetch, './products')"
)
// 创建一个模拟的 error 对象
const error = {}
// 期望一个 dispatch 指令
assert.deepEqual(
iterator.throw(error).value, put({ type: 'PRODUCTS_REQUEST_FAILED', error }),
"fetchProducts should yield an Effect put({ type: 'PRODUCTS_REQUEST_FAILED', error })"
)
//官网还提供了一种捕捉 Promise 的拒绝操作,并将它们映射到一个错误字段对象,可以查阅。个人喜欢第一种错误处理方式

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 最近项目用了dva,dva对于异步action的处理是用了redux-saga,故简单学习了下redux-saga...
    笨人不能懒阅读 2,825评论 0 5
  • redux-saga框架使用详解及Demo教程 前面我们讲解过redux框架和dva框架的基本使用,因为dva框架...
    光强_上海阅读 22,032评论 8 46
  • Redux-saga 概述 在 redux 一文中我们有说过处理异步我们应该放在 reducer 之前,所以我们需...
    满是裂缝的花卷阅读 2,418评论 0 2
  • Redux-saga 概述 redux-saga是一个用于管理redux应用异步操作的中间件,redux-saga...
    woow_wu7阅读 51,654评论 11 41
  • 1. redux-thunk处理副作用的缺点 1.1 redux的副作用处理 redux中的数据流大致是: UI—...
    Grace_ji阅读 3,532评论 0 14