Angular 6中如何自定义RxJS可管道操作符并正确导入pipe?
解决NgRx Effect中自定义RxJS操作符及导入问题
一、修复pipe导入的黑名单错误
首先,你遇到的从rxjs/Rx导入pipe触发黑名单错误,是因为全量导入rxjs/Rx会引入整个RxJS库,导致打包体积冗余,很多项目的Lint规则(比如ESLint的rxjs/no-import-from-rx)会禁止这种做法。正确的导入方式是按需导入:
- 基础类型(如
Observable)和工具函数(如pipe)从rxjs导入 - 具体操作符(如
withLatestFrom、map)从rxjs/operators导入 - NgRx的
ofType操作符从@ngrx/effects导入
示例导入代码:
import { Observable } from 'rxjs'; import { withLatestFrom, map } from 'rxjs/operators'; import { ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; // 其他必要导入(如action类型、reducers等)
二、实现自定义getDefaultTimezoneId管道操作符
你的需求是把重复的时区处理逻辑封装成可复用的操作符,这里我们可以创建一个工厂函数式的操作符(因为需要依赖NgRx Store获取时区数据),具体步骤如下:
1. 定义自定义操作符
创建一个单独的文件(比如timezone.operators.ts),封装时区处理逻辑:
import { pipe } from 'rxjs'; import { withLatestFrom, map } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { fromCore } from '../reducers/core.reducer'; // 替换为你的core reducer实际路径 import { DATE_TYPE } from '../constants/date.constants'; // 替换为你的DATE_TYPE定义实际路径 // 工厂函数:接收Store实例,返回RxJS操作符 export const getDefaultTimezoneId = (store: Store) => pipe( // 合并当前流数据与Store中的时区列表 withLatestFrom(store.select(fromCore.getTimezones)), // 处理时区逻辑,返回包含defaultTimezoneId的新数据流 map(([[action, mappingFields], timezones]) => { const { fieldType } = action.payload; // 找到默认时区,添加空值保护避免报错 const defaultTimezone = timezones.find(tz => tz.isDefault); const timezoneId = fieldType === DATE_TYPE ? (defaultTimezone?.id || '') : ''; // 返回原数据+处理后的时区ID return [action, mappingFields, timezoneId]; }) );
2. 在Effect中使用自定义操作符
回到你的Effect文件,注入Store后,调用自定义操作符并传入Store实例:
@Injectable() export class EditableObjectSchemaEffects { constructor( private actions$: Actions, private store: Store ) {} @Effect() updateMappingAfterChangeFieldType$ = this.actions$.pipe( ofType(EditableObjectSchemaActionTypes.EditFieldType), withLatestFrom(this.store.select(fromReducers.getMappingFields)), // 调用自定义操作符,传入store实例 getDefaultTimezoneId(this.store), map(([action, mappingFields, defaultTimezoneId]: [EditFieldType, MappingModel[], string]) => { const { uuid } = action.payload; const fieldForUpdate = mappingFields.find(field => field.uuid === uuid); return new UpdateExistingMapping({ ...fieldForUpdate, timezoneId: defaultTimezoneId }); }) ); }
补充说明
- 为什么用工厂函数?因为自定义操作符需要访问Store的时区数据,通过传入Store实例,我们可以在操作符内部调用
store.select获取所需状态,同时保证操作符可以在不同Effect中复用。 - 空值处理:添加了
defaultTimezone?.id || ''的空值保护,避免找不到默认时区时出现运行时错误。
内容的提问来源于stack exchange,提问作者mr__brainwash
相关产品推荐
相关产品推荐

