1

假设你有一个简单的 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 实例本身中实现修复更有意义。

我的问题是:在触发其订阅者之前,是否有钩子或任何其他方式对每个“下一个”值应用一些更改?换句话说,在我的代码完成之后

instance.countryOfBirth = CountryEnum.US;

在触发任何订阅者之前,我想检查该值是否为字符串(例如:US),如果是,我想获取相应的 CountryEnum 实例并将其传递给“下一个”调用而不是原始的“美国”字符串。

在代码中它看起来像

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 中找到任何可以做我想做的事情。

您的帮助将不胜感激!

4

1 回答 1

3

由于显然没有现成的方法来做我需要的事情,这就是我使用@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.

希望这对某人有帮助!

于 2016-10-22T16:52:13.050 回答