zoukankan      html  css  js  c++  java
  • redux-saga学习基础篇一

    今日学习目录

    一、 基本入门

    二、 为了让代码便于测试

    三、call、apply、cps

    四、dispatch、put

    一、 基本入门

    创建一个 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 })"
    )
    
    
  • 相关阅读:
    【JAVA基础】强引用、弱引用、软引用、虚引用
    检测手机传感器【Sensor】
    Nginx下搭建flv视频服务器且支持视频拖动进度条播放
    盘点Web开源项目大集合【太全了!!】
    打造属于自己的Notepad++
    魔兽1.20E作弊内存地址全公开
    万能的js复制按钮
    js定时刷新网页
    解决flv格式视频在网页中播放问题
    程序员该如何学习新知识
  • 原文地址:https://www.cnblogs.com/fe-linjin/p/11134653.html
Copyright © 2011-2022 走看看