redux-saga学习基础篇一

时间:2019-07-04
本文章向大家介绍redux-saga学习基础篇一,主要包括redux-saga学习基础篇一使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、 基本入门

创建一个 sagas.js 的文件,然后添加以下代码片段:

// sagas.js
export function* helloSaga() {
  console.log('Hello Sagas!');
}

为了运行我们的 Saga,我们需要:

  • 创建一个 Saga middleware 和要运行的 Sagas(目前我们只有一个 helloSaga)
  • 将这个 Saga middleware 连接至 Redux store.
// main.js ...
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'

//...
import { helloSaga } from './sagas'

const sagaMiddle = createSagaMidlleware(helloSaga)

const store = createStore(
  reducer,
  applyMiddleware(sagaMiddle )
)
sagaMiddle.run(helloSaga) 
// rest unchanged

运行 helloSaga 之前,我们必须使用 applyMiddleware 将 middleware 连接至 Store。然后使用 sagaMiddleware.run(helloSaga) 运行 Saga。

二、 为了让代码便于测试

import { call } from 'redux-saga/effects'
import Api from '...'

const iterator = fetchProducts()

// expects a call instruction
assert.deepEqual(
  iterator.next().value,
  call(Api.fetch, '/products'),
  "fetchProducts should yield an Effect call(Api.fetch, './products')"
)

这些 声明式调用(declarative calls) 的优势是,我们可以通过简单地遍历 Generator 并在 yield 后的成功的值上面做一个 deepEqual 测试, 就能测试 Saga 中所有的逻辑。这是一个真正的好处,因为复杂的异步操作都不再是黑盒,你可以详细地测试操作逻辑,不管它有多么复杂。

三、call、apply、cps

// Effect -> 调用 Api.fetch 函数并传递 `./products` 作为参数
{
  CALL: {
    fn: Api.fetch,
    args: ['./products']  
  }
}

call 同样支持调用对象方法,你可以使用以下形式,为调用的函数提供一个 this 上下文:

yield call([obj, obj.method], arg1, arg2, ...) 
// 如同 obj.method(arg1, arg2 ...)

apply 提供了另外一种调用的方式:

yield apply(obj, obj.method, [arg1, arg2, ...])

call 和 apply 非常适合返回 Promise 结果的函数。另外一个函数 cps 可以用来处理 Node 风格的函数 (例如,fn(...args, callback) 中的 callback 是 (error, result) => () 这样的形式,cps 表示的是延续传递风格(Continuation Passing Style))。

import { cps } from 'redux-saga'

const content = yield cps(readFile, '/path/to/file')

当然你也可以像测试 call 一样测试它:

import { cps } from 'redux-saga/effects'

const iterator = fetchSaga()
assert.deepEqual(iterator.next().value, cps(readFile, '/path/to/file') )

四、dispatch、put

//... 传统dispatch,不便于测试

function* fetchProducts(dispatch)
  const products = yield call(Api.fetch, '/products')
  dispatch({ type: 'PRODUCTS_RECEIVED', products })
}

redux-saga 为此提供了另外一个函数 put,这个函数用于创建 dispatch Effect。

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

现在,我们可以像上一节那样轻易地测试 Generator:

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

原文地址:https://www.cnblogs.com/fe-linjin/p/11134653.html