假设您有一个简单的BehaviorSubject
this.countryOfBirth$ = new BehaviorSubject<CountryEnum>(null);
get countryOfBirth() {
return this.countryOfBirth$.value;
};
set countryOfBirth(val: CountryEnum) {
this.countryOfBirth$.next(val);
};
这样做instance.countryOfBirth
会返回最后一个值,而instance.countryOfBirth = CountryEnum.US
会将新值推送到主题。
我遇到的问题是我将此主题实例传递给自定义模型驱动的表单模块,默认情况下会错误地传递字符串而不是我的CountryEnum
类的实例。
我可以在表单模块中解决这个问题,但我希望尽可能将其与任何特定于应用程序的逻辑分离,以便在BehaviorSubject实例本身中实现修复更有意义。
我的问题是:是否有钩子或任何其他方式对每一个&#34; next&#34;进行一些更改。在它触发订户之前的价值?换句话说,在我的代码之后
instance.countryOfBirth = CountryEnum.US;
在触发任何订阅者之前,我想检查该值是否为字符串(例如:US),如果是 - 我想获取相应的CountryEnum实例并将其传递给&#34; next&# 34;打电话代替原来的&#34;美国&#34;字符串。
在代码中它看起来像
this.countryOfBirth$.onBeforeNext((val) => {
if (typeof val == "string") {
return CountryEnum.getInstance(val);
} else if (val instanceof CountryEnum) {
return val;
} else {
throw new Error("Unsupported value type");
}
});
但显然onBeforeNext
并不存在,而且我似乎无法在dox中找到任何可以做我想做的事情。
非常感谢您的帮助!
答案 0 :(得分:2)
由于显然没有现成的方法来完成我需要的工作,所以我是如何使用@estus在评论中提到的方法实现我的解决方案的:
// BehaviorSubjectWithValidation.ts
import { BehaviorSubject } from "rxjs/BehaviorSubject";
export class BehaviorSubjectWithValidation<T> extends BehaviorSubject<T> {
private _validator: (val: T) => T;
constructor(defaultValue: T, validator: (val: T) => T) {
super(defaultValue);
this._validator = validator;
}
next(value: T): void {
if (this._validator) {
value = this._validator(value);
}
super.next(value);
}
}
然后在我的CountryEnum
课程中,我添加了以下方法
public static parse: (val: any) => CountryEnum = (val: any) => {
if (val) {
if (typeof val === "string") {
return CountryEnum.getInstance(val);
} else if (val instanceof CountryEnum) {
return val;
} else {
throw new Error("Unsupported CountryEnum value");
}
} else {
throw new Error("Invalid country");
}
}
然后我在主应用程序的逻辑中以下列方式使用它:
this.countryOfBirth$ =
new BehaviorSubjectWithValidation<CountryEnum>(null, CountryEnum.parse);
所以,现在我的代码的任何部分都为this.countryOfBirth$
添加了一个新值,它将始终通过CountryEnum.parse
过滤它。
希望这有助于某人!