usar Services en angular, es la manera mas facil de hacer muchas cosas, desde comunicar componentes hasta consumir webservices o cualquier otra tarea.
Services o servicios en angular es una forma de trabajar de manera síncrona con datos y llamadas.
Los procesos síncronos son procesos que se llevan a cabo en intervalos conocidos y constantes.
https://sistemas.com/sincrono.php
Es decir que si vamos a consumir un webservices no necesitamos hacer esperar a nuestro usuario como normalmente se acostumbraba.
Importancia de usar services en angular
La propia página de angular te explica que los servicios deben ser usados para procesar algo y los componentes nunca deberían guardar datos ni presentar datos falsos .
Los servicios se encargan en traer datos y los componentes en presentarlos de manera correcta.
En esta entrada explico un poco más como funciona los servicios y también como consumir un webservices.
para explicar esto usaremos el ejemplo de una calculadora, donde todas la logica y operación quedara fuera de los componentes para tener un solo servicio.
La idea principal es tener una segunda vista que obtendrá todos los resultados de nuestra calculadora.
El servicio que vamos a crear nuestra lógica y también comunicar otros componentes.
Creación de calculadora en angular
Vamos a comenzar a ver un poco de código, tendremos dividido el proyecto en 2 vistas, uno es la calculadora y la otra una pantalla de visualización y tendremos un servicio.
calculadora con angular
<div class="calculadora"> <div class="pantalla"> <div class="operacion"> {{mirame}} </div> <div class="resultado"> {{resultado}} </div> </div> <div class="numeros"> <div (click)="op(9)">9</div> <div (click)="op(8)">8</div> <div (click)="op(7)">7</div> <div (click)="op('/')">/</div> <div (click)="op(6)">6</div> <div (click)="op(5)">5</div> <div (click)="op(4)">4</div> <div (click)="op('x')">x</div> <div (click)="op(3)">3</div> <div (click)="op(2)">2</div> <div (click)="op(1)">1</div> <div (click)="op('+')">+</div> <div (click)="op('.')">.</div> <div (click)="op(0)">0</div> <div (click)="op('c')">Borrar</div> <div (click)="op('-')">-</div> <div>Un</div> <div>Programador</div> <div>.com</div> <div (click)="igual()" style="background-color: red;">=</div> </div> </div>
css
.calculadora { display: flex; flex-direction: column; flex-wrap: nowrap; justify-content: center; align-content: center; } .pantalla { min-height: 100px; border: 1px solid whitesmoke; margin-bottom: 5px; margin-top: 2px; display: flex; flex-direction: column; flex-wrap: wrap; padding: 2px 10px; } .operacion { min-height: 50px; text-align: right; font-size: x-large; } .resultado { min-height: 50px; text-align: right; font-size: large; color: grey; } .numeros { display: grid; grid-template-columns: auto auto auto auto; text-align: center; font-size: xx-large; } .numeros div { border-radius: 10px; transition: all 500ms linear; cursor: pointer; } .numeros div:hover { background-color: rgba(255, 255, 255, 0.3); }
TS
import { Component, OnInit } from '@angular/core'; import { IgualService } from '../igual.service'; @Component({ selector: 'app-calcu', templateUrl: './calcu.component.html', styleUrls: ['./calcu.component.css'] }) export class CalcuComponent implements OnInit { operacion: string; o1: number; signo: boolean; mirame: string; resultado: number; ss: string; constructor(private logic: IgualService) { } ngOnInit() { this.resultado = 0; this.operacion = '0'; this.signo = false; this.mirame = '0'; this.ss = ''; this.logic.getResultado().subscribe(r => { this.resultado = r; }); this.op(0); } op(datos) { this.logic.op(datos).subscribe(s => { this.mirame = s; }); } igual() { this.logic.getIgual(); } }
Podemos ver que el código es muy limpio, como se había explicado anteriormente el componente debe estar limpio y su único trabajo es imprimir y obtener la interacción.
Vista pantalla 2
<div class="upantalla"> <h2>Resultados: </h2> <p>{{result}}</p> </div>
.upantalla { display: flex; width: 100%; height: 150px; flex-direction: column; flex-wrap: nowrap; justify-content: center; align-content: center; color: red; font-size: xx-large; font-weight: bold; overflow-y: auto; } h2 { color: aliceblue; }
import { Component, OnInit } from '@angular/core'; import { IgualService } from '../igual.service'; @Component({ selector: 'app-vista', templateUrl: './vista.component.html', styleUrls: ['./vista.component.css'] }) export class VistaComponent implements OnInit { result: string; constructor(private igual: IgualService) { } ngOnInit() { this.result = ''; this.igual.getResultado().subscribe(x => { this.result = this.result + x + ' \n'; }); } }
Service calculadora
import { Injectable } from '@angular/core'; import { Observable, Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class IgualService { operacion = ''; o1 = 0; signo = false; mirame$ = new Subject<string>(); resultado$ = new Subject<number>(); ss: string; _ss = []; operac: number; constructor() { } op(teclas: any): Observable<string> { if (this.o1 > 0 && this.ss === '' && !isNaN(teclas)) { this.operacion = '0'; this.o1 = 0; this.resultado$.next(0); } switch (teclas) { case 0: if (this.operacion !== '0') { this.operacion = this.operacion + '0'; } break; case 1: if (!this.sicero('1')) { this.operacion = this.operacion + '1'; } break; case 2: if (!this.sicero('2')) { this.operacion = this.operacion + '2'; } break; case 3: if (!this.sicero('3')) { this.operacion = this.operacion + '3'; } break; case 4: if (!this.sicero('4')) { this.operacion = this.operacion + '4'; } break; case 5: if (!this.sicero('5')) { this.operacion = this.operacion + '5'; } break; case 6: if (!this.sicero('6')) { this.operacion = this.operacion + '6'; } break; case 7: if (!this.sicero('7')) { this.operacion = this.operacion + '7'; } break; case 8: if (!this.sicero('8')) { this.operacion = this.operacion + '8'; } break; case 9: if (!this.sicero('9')) { this.operacion = this.operacion + '9'; } break; case '/': this.logicOpera('/'); this.ss = '/'; this._ss.push('/'); break; case 'x': this.logicOpera('*'); this.ss = '*'; this._ss.push('*'); break; case '+': this.logicOpera('+'); this.ss = '+'; this._ss.push('+'); break; case 'c': this.operacion = this.operacion.substring(0, ((this.operacion.length) - 1)); if (this.operacion.length === 0) { this.signo = false; this.o1 = 0; this.resultado$.next(0); this.operacion = '0'; this.operac = 0; this.ss = ''; this._ss.length = 0; } break; case '-': this.logicOpera('-'); this.ss = '-'; this._ss.push('-'); break; case '.': if (this.operacion.indexOf('.') === -1) { this.operacion = this.operacion + '.'; } break; } if (!this.signo && this.o1 === 0) { this.mirame$.next(this.operacion); } else { if (this.ss === '') { this.mirame$.next(this.operacion); } else { this.mirame$.next(this.o1 + this.ss + this.operacion); } this.mirame$.next(this.o1 + this.ss + this.operacion); } return this.mirame$.asObservable(); } logicOpera(sy: string) { if (!this.signo && this.o1 === 0) { this.o1 = parseFloat(this.operacion); this.operacion = '0'; this.signo = true; } else { if (this.o1 > 0 && !this.signo) { this.mirame$.next(this.o1 + this.ss + this.operacion); this._ss.push(sy); this.ss = sy; this.signo = true; } else { if (this._ss.length < 2 || this._ss[(this._ss.length - 1)] === sy) { this.o1 = this.opera(this.o1, this.operacion, sy); } else { this.o1 = this.opera(this.o1, this.operacion, this._ss[(this._ss.length - 1)]); } this.resultado$.next(this.o1); this.operacion = '0'; } } } opera(op1, op2, sig) { switch (sig) { case '+': this.operac = (op1 + parseFloat(op2)); break; case '-': this.operac = (op1 - parseFloat(op2)); break; case '/': this.operac = (op1 / parseFloat(op2)); break; case '*': this.operac = (op1 * parseFloat(op2)); break; } return this.operac; } sicero(remplazo) { if (this.operacion === '0') { this.operacion = remplazo; return true; } return false; } getResultado(): Observable<number> { return this.resultado$.asObservable(); } getIgual() { let x; if (this._ss.length === 0) { this.o1 = parseFloat(this.operacion); this.operacion = '0'; this.ss = '+'; x = this.opera(this.o1, this.operacion, this.ss); } else if (this._ss.length === 1) { x = this.opera(this.o1, this.operacion, this.ss); } else { x = this.opera(this.o1, this.operacion, this._ss[(this._ss.length - 1)]); } this.resultado$.next(x); this.mirame$.next(''); this.ss = ''; this.signo = false; this.o1 = x; this.operacion = '0'; this._ss.length = 0; } }
Toda la lógica de nuestra calculadora quedó en un solo lugar, tambien ahi mismo compartiremos información a otros componentes que se suscriban.
Si no reconoces o no sabes que es Subject en angular te recomiendo ver este post.
Una ventaja es que creamos funciones para cada cosa y al estar en el services cualquier elemento puedo consumir el mismo método.
También podemos pasar información en tiempo real de manera muy sencilla y no bloqueamos nada para el usuario.