What is the best way to validate the data of an observable in RxJS?

0

I have the following code:

    class IPHeaderComponentController extends App.Core.Domain.BaseController {

    public api: ApiRule = {};

    public exception: Error = null;

    static $inject = ['ipService', 'loggerServices', '$scope'];

    constructor(private IpService: IpService, private loggerServices: Core.Services.ILoggerServices, private $scope: angular.IScope) {

        super();

        Rx.Observable.fromEvent(document.getElementById('btnRule'), 'click').subscribe(() => this.add());

        this.IpService.errors$.subscribe((exception: Error) => {
            if (exception !== null) {
                this.loggerServices.error(exception.message, exception.name);
                this.exception = exception;
            }
        });
    }

    private add = () => {

        this.IpService.validateRule(this.api);

        if (this.exception === null) {

            this.IpService.addRule(this.api.rule, this.api.source, this.api.destiny);

            this.$scope.$applyAsync(() => {
                this.api.rule = "";
                this.api.source = "";
                this.api.destiny = "";
            });

        } else {
            this.exception = null;
        }
    };

}

In the component's constructor, I subscribe to an observable where form errors are sent.

            this.IpService.errors$.subscribe((exception: Error) => {
            if (exception !== null) {
                this.loggerServices.error(exception.message, exception.name);
                this.exception = exception;
            }
        });

If they are fixed, I have a property in the component that is called exception that is of type Error and that I initialize it to null.

this.IpService.validateRule(this.api);

        if (this.exception === null) {

            this.IpService.addRule(this.api.rule, this.api.source, this.api.destiny);

            this.$scope.$applyAsync(() => {
                this.api.rule = "";
                this.api.source = "";
                this.api.destiny = "";
            });

        } else {
            this.exception = null;
        }

When errors $ emits an error I check that the error is not null, if so, then I equal it (I use it as a sneak variable) that is, if it is different from null, there was an error. Then I assign it again the value null.

The service that contains all the business logic is as follows:

namespace App.Service.Services {
import Subject = Rx.Subject;
import ApiRule = App.Apis.Saa.Domain.ApiRule;
import Observable = Rx.Observable;
import BehaviorSubject = Rx.BehaviorSubject;

type ApiRulesOperation = (rules: ApiRule[]) => ApiRule[];

const initialRules: ApiRule[] = JSON.parse(sessionStorage.getItem('angular-rxjs-rules')) || [];

export class IpService {

    public rules$: Observable<ApiRule[]>;

    public errors$: Subject<Error> = new Subject<Error>();

    private update$: BehaviorSubject<ApiRulesOperation> = new BehaviorSubject<ApiRulesOperation>((rules: ApiRule[]) => rules);

    private validateRule$: Subject<ApiRule> = new Subject<ApiRule>();

    private createRule$: Subject<ApiRule> = new Subject<ApiRule>();

    private modifyRule$: Subject<ApiRule> = new Subject<ApiRule>();

    private removeRule$: Subject<string> = new Subject<string>();

    private ruleRepeatedValidate$: Subject<ApiRule> = new Subject<ApiRule>();

    private ipStartFormatValidate$: Subject<ApiRule> = new Subject<ApiRule>();

    private ipEndFormatValidate$: Subject<ApiRule> = new Subject<ApiRule>();

    private create$: Subject<ApiRule> = new Subject<ApiRule>();

    private modify$: Subject<ApiRule> = new Subject<ApiRule>();

    private remove$: Subject<string> = new Subject<string>();

    constructor() {

        this.rules$ = this.update$
            .scan((rules: ApiRule[], operation: ApiRulesOperation) => operation(rules), initialRules)
            .shareReplay(1);

        this.rules$.forEach(rules => sessionStorage.setItem('angular-rxjs-rules', JSON.stringify(rules)));

        this.ruleRepeatedValidate$.map((rule: ApiRule): Error => {

            let exception: Error = null;

            const search = initialRules.find(t => t.rule === rule.rule);

            if (search !== undefined) {

                exception = {
                    name: "Regla repetida",
                    message: "No se puede repetir el nombre de la regla."
                };
            }

            return exception;


        }).subscribe(this.errors$);

        this.ipStartFormatValidate$.map((rule: ApiRule): Error => {

            let exception: Error = null;

            if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.source))) {

                exception = {
                    name: "IP Inicial",
                    message: "La IP inicial no tiene el formato correcto."
                };
            }

            return exception;

        }).subscribe(this.errors$);

        this.ipEndFormatValidate$.map((rule: ApiRule): Error => {

            let exception: Error = null;

            console.log("Destiny: ", rule.destiny);

            if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.destiny))) {
                exception = {
                    name: "IP Final",
                    message: "La IP final no tiene el formato correcto."
                };
            }

            return exception;

        }).subscribe(this.errors$);

        this.create$.map((rule: ApiRule): ApiRulesOperation => {
            return (rules: ApiRule[]) => {
                const search = rules.find(t => t.rule === rule.rule);
                if (search !== undefined) {
                    return rules;
                } else {
                    return rules.concat(rule);
                }
            }
        });

        this.modify$
            .map((rule: ApiRule): ApiRulesOperation => {
                return (rules: ApiRule[]) => {
                    const modifyRule = rules.find(t => t.rule === rule.rule);
                    modifyRule.rule = rule.rule;
                    modifyRule.destiny = rule.destiny;
                    modifyRule.source = rule.source;
                    return rules;
                };
            })
            .subscribe(this.update$);

        this.remove$
            .map((name: string): ApiRulesOperation => (rules: ApiRule[]) => rules.filter(rule => rule.rule !== name))
            .subscribe(this.update$);

        this.createRule$
            .subscribe(this.create$);

        this.validateRule$.subscribe(this.ruleRepeatedValidate$);

        this.validateRule$.subscribe(this.ipStartFormatValidate$);

        this.validateRule$.subscribe(this.ipEndFormatValidate$);

        this.modifyRule$
            .subscribe(this.modify$);

        this.removeRule$
            .subscribe(this.remove$);
    }

    public addRule = (rule: string, source: string, destiny: string): void => {
        let newRule: ApiRule = {
            rule: rule,
            source: source,
            destiny: destiny
        };
        this.createRule$.onNext(newRule);
    };

    public modifyRule(rule: ApiRule): void {
        this.modifyRule$.onNext(rule);
    }

    public removeRule(name: string): void {
        this.removeRule$.onNext(name);
    }

    public validateRule(rule: ApiRule) {
        this.validateRule$.onNext(rule);
    }

}

angular
    .module("app.service")
    .service("ipService", IpService);}

These are the ones that are in charge of validating the rules:

            this.ruleRepeatedValidate$.map((rule: ApiRule): Error => {

            let exception: Error = null;

            const search = initialRules.find(t => t.rule === rule.rule);

            if (search !== undefined) {

                exception = {
                    name: "Regla repetida",
                    message: "No se puede repetir el nombre de la regla."
                };
            }

            return exception;


        }).subscribe(this.errors$);

        this.ipStartFormatValidate$.map((rule: ApiRule): Error => {

            let exception: Error = null;

            if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.source))) {

                exception = {
                    name: "IP Inicial",
                    message: "La IP inicial no tiene el formato correcto."
                };
            }

            return exception;

        }).subscribe(this.errors$);

        this.ipEndFormatValidate$.map((rule: ApiRule): Error => {

            let exception: Error = null;

            console.log("Destiny: ", rule.destiny);

            if (!(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(rule.destiny))) {
                exception = {
                    name: "IP Final",
                    message: "La IP final no tiene el formato correcto."
                };
            }

            return exception;

        }).subscribe(this.errors$);

The way I'm using works correctly, but I do not think it's the right one. Can someone tell me another way to validate the data? What I'm looking for is to remove the snooping variable (exception) and use a more appropriate way for it to be the flow that indicates whether to continue adding or not adding the rule.

    
asked by Francisco Javier Estrella Rodr 10.12.2018 в 16:12
source

0 answers