技术分享- RxJS与Redux-Observable简介

本文介绍了如何在项目中单独使用RxJS的Subject,强调了其在处理异步和时间操作上的优势。接着详细讲解了Redux-Observable,它是与RxJS结合的Redux中间件,用于处理action流。文中提到了Epic的基本概念,如何创建和组合Epic,并强调了Redux-Observable的兼容性和在特定场景下的应用,包括异步轮询、延迟操作和同步化请求等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RxJS 在项目中单独使用


单独使用RxJS提供的Subject来使用功能
一个组件的construtor中, 我们声明了如下的Subject
this.inputSubject = new Rx.Subject();
// 声明从收到数据,到数据传递给最终的数据订阅者,之间需要经过的数据处理管道
inputSubject
.debounceTime(1000)
.filter(value => value !== 'aa')
.do(value => setTitle(`搜索${value}中...`))
.concatMap(value => Rx.Observable.fromPromise(asyncQuery(value)))
.do(result => setTitle(`搜索${result.value}成功`))
.subscribe(updateList);
之后再在任何地方,我们拥有了对应的数据,需要把这个数据经过我们定义好的数据处理管道之后调用最终的updateList, 只需要如下的调用
<TextInput onChangeText={value => this.inputSubject.next(value)} />
这样的涉及各种异步和时间处理的写法不仅更加优雅, 而且后续进行修改来实现其他的功能也更加方便

Redux-Observable


Redux-Observable是配合RxJS使用的一个框架,用来在已有的redux框架下面添加一个中间件,把redux中的dispatch出来的action封装成一个流对象,之后使用RxJS的各种操作符对这个action进行各种操作。
安装过程
npm install redux-observable --save
npm install rxjs --save 

Epic

Redux-Observable基本的操作单元是Epic,其本质是如下的一个函数
(action$, store) => (
    action$.ofType('ACTION_TO_BE_LISTEN')
    // ... All the processes and operators
    .map(e => ({ 
        type: 'NEW_DISPATCH_ACTION', 
    })) // finally dispatch a Observable back to the middleware
)
action$为传入的流对象,传入之后需要使用ofTypefilter之类的过滤操作符筛选出来这个Epic需要监听的dispatch,之后对这个流时间各种RxJS里面定义的操作,最后生成一个新的Observable对象返回给redux中间件做后续的处理(调用其他action或者通过reducer更新store)
epic声明时候,使用redux-observable提供的combineEpics方法来把声明的各种Epic合成到一起
const epic1 = action.ofType('ACTION_A').mapTo({ type: 'action_a' })
const epic2 = action.ofType('ACTION_B').mapTo({ type: 'action_b' })
const epic3 = action.ofType('ACTION_C').mapTo({ type: 'action_c' })
// ... So many epic here
import { combineEpics } from 'redux-observable';

const combinedEpics = combineEpics(epic1, epic2, ....)
和Reducer的声明非常类似。声明并生成了一个合并后的Epic,之后把这个Epic使用redux-observable提供的方法生成对应的中间件,在我们的RNX项目里面方法如下:
import { createEpicMiddleware } from 'redux-observable';
import combinedEpics from '../epics';

// RNX 配置项目, 本人自己使用的React框架是RNX
// 对于其他的Redux框架
// 在配置middleware的地方做类似操作即可
RNPlus.defaults.redux = {
    // ... other configs like configing the reducers
    middleware: [createEpicMiddleware(combinedEpics)],
}
参考项目blibee-demo里面的声明和使用epic的方法,可以看出这个框架可以很好的和我们现在的redux体系兼容
项目结构
    some-action
        |-index.js // 之前各种actions放置的地方
        |-epic.js // 这个action里面需要使用epic来进行流控制的逻辑
        |-query.js // 各种网络请求的, 都封装成一个简单的返回Promise的函数
其只是在现有redux基础上做功能的增量,任何epic没有涉及到的action都不会受到任何影响,保证了引入框架时候的兼容性。

开始介绍几个实际的demo

Redux-Observable使用中需要注意的问题

  • epic不能把传入的action流对象原样返回回去,这样会造成无限循环导致栈溢出。

    // 一个type为SOME_ACTION_NAME的action不做处理就返回,会导致无限递归
    action => (
        action.ofType('SOME_ACTION_NAME')
    )
    // 这样的只对传入的Observable进行时间维度的操作,
    // 仍然是把原先的action未做处理返回,仍然会导致无限递归
    action => (
        action.ofType('SOME_ACTION_NAME')
        .delay(1000)
        .debounceTime(3000)
    )
    
  • 外界dispatch对应的action的时候,在redux框架里面,这个action是先派发到reducer里面进行处理,reducer中处理并更新过store之后,才到相同名称的epic中

    // in reducer 
    import  { handleActions } from 'redux-actions';
    
    export default handleActions({
        SOME_EPIC_ACTION_SHARE_NAME(store, action) {
            return { ...store, count: store.count + 1 };
        },
    }, { count: 0 });
    ...
    
    // in epic
    (action, store) => action.ofType('SOME_EPIC_ACTION_SHARE_NAME')
    .do(() => console.log(store.getState())
    ...
    
    // in view
    dispatch(createAction('SOME_EPIC_ACTION_SHARE_NAME'));
    ...
    
    // 对应的输出结果
    // { count: 1 }
    
  • 监听同一个action的多个epic之间没有固定的执行顺序,全部按照epic流执行情况处理

    case1:

    // in epics
    action => action.ofType('SOME_ACTION')
    .do(() => console.log('epic 1')); 
    
    action => action.ofType('SOME_ACTION')
    .do(() => console.log('epic 2'));
    
    // in view
    dispatch(createAction('SOME_ACTION'))
    
    // result will be
    // epic1
    // epic2
    

    case2:

    // in epics
    action => action.ofType('SOME_ACTION')
    .delay(2000)
    .do(() => console.log('epic 1')); 
    
    action => action.ofType('SOME_ACTION')
    .do(() => console.log('epic 2'));
    
    // in view
    dispatch(createAction('SOME_ACTION'))
    
    // result will be
    // epic2 
    // epic1    (after two second)
    

使用redux-observable来实现一些常规写法十分难以开发的场景。

  1. 异步轮询请求
  2. 按钮的delay/delayTime, buffer
  3. 异步请求的同步化/序列化
  4. 同步多个间隔不一样的轮询器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值