Angular 2 observed subscriptions arrow functions get big and dirty

I want to know if there is a better way to define the angular 2 callback functions of observed subscriptions when working with http calls without breaking the principle of uniform responsibility , when it comes to the built-in logic, it leads to an ugly dirty code .

I am trying to use function variables instead of arrow functions to separate callback logic, but I cannot access this and local function variables ( state in the example).

 updateState(state: string) { let proposition = new Proposition(); proposition.id = this.id; proposition.state = state; this.propositionService.updateProposition(proposition).subscribe( (data) => { .... // instruction using local variable this.router.navigate(['/portfolio', state]); .... }, ..... // instrution using this (errors) => this.toastr.warning('Error.', 'ops !'); .....} 
+5
source share
1 answer

There are many options, and all have problems and disadvantages. You must choose the one that has the most votes and the least number of minuses in each case.

Here are a few options (there are many more)

  • Create a local binding for the arrow function.

     updateState(state: string) { const withNext = (data: { values: {}[] }) => { console.info(data.values); .... // instruction using local variable this.router.navigate(['/portfolio', state]); .... }; const withError = error => { this.toastr.warning('Error.', error); } this.propositionService.updateProposition(proposition) .subscribe(withNext, withError); } 

    The disadvantages of this approach are that you need to create callbacks before using them, since the assignments will not be raised, and you will lose the type of output of the callback arguments, requiring a recount of the types of the arguments.

  • To get around the declaration order problem, we can create a local function declaration

     updateState(state: string) { this.propositionService.updateProposition(proposition) .subscribe(withNext, withError); const that = this; function withNext(data: { values: {}[] }) { console.info(data.values); .... // instruction using local variable that.router.navigate(['/portfolio', state]); .... } function withError(error) { that.toastr.warning('Error.', error); } } 

    The drawbacks of this approach are that you need to execute the this alias, and again we lose type inference and should resort to redundancy and possibly incorrectly specify the types of callback arguments.

  • If the observable only emits one value, for example, if it represents an HTTP request, we can use toPromise and enjoy crisp and clean code with a full type of output and not need callbacks.

     async updateState(state: string) { try { const data = await this.propositionService.updateProposition(proposition) .toPromise(); console.info(data.values); .... // instruction using local variable this.router.navigate(['/portfolio', state]); .... } catch (error) { this.toastr.warning('Error.', error); } } 

    The disadvantage is that this approach only works for observables that emit no more than one value (for example, HTTP requests).

The state parameter is available for all local ads regardless of approach and is not a factor if you do not want to extract success and failure logic to a location outside of the updateState method.

+2
source

Source: https://habr.com/ru/post/1264068/


All Articles