function suma(a, b) { return a + b; }
console.log(“Inicio”); console.log(suma(2, 3)); // Salida: 5 console.log(“Fin”);
- Resultado Esperado:
```console
Inicio
5
Fin
Promesa
function obtenerDatos() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Datos obtenidos");
}, 2000);
});
}
console.log("Inicio");
obtenerDatos().then((resultado) => {
console.log(resultado); // Salida: Datos obtenidos
});
console.log("Fin");
Inicio
Fin
Datos obtenidos
async function ejecutar() {
console.log("Inicio");
const resultado = await obtenerDatos();
console.log(resultado); // Salida: Datos obtenidos
console.log("Fin");
}
ejecutar();
Inicio
Datos obtenidos
Fin
const miPromesa = new Promise((resolve, reject) => {
const exito = true; // Simulación de una condición
if (exito) {
resolve("Operación exitosa");
} else {
reject("Error en la operación");
}
});
then(): Se ejecuta cuando la promesa es cumplida. catch(): Se ejecuta cuando la promesa es rechazada.
miPromesa
.then((resultado) => {
console.log(resultado); // Salida: Operación exitosa
})
.catch((error) => {
console.error(error); // En caso de error
});
const promesaEncadenada = new Promise((resolve) => {
resolve(5);
});
promesaEncadenada
.then((resultado) => resultado * 2)
.then((resultado) => resultado + 3)
.then((resultadoFinal) => {
console.log(resultadoFinal); // Salida: 13
});
A veces, es necesario ejecutar múltiples promesas en paralelo. Para esto, se pueden utilizar métodos como Promise.all() y Promise.race().
const promesa1 = Promise.resolve(3);
const promesa2 = new Promise((resolve) => setTimeout(resolve, 100, '¡Hola!'));
const promesa3 = 42;
Promise.all([promesa1, promesa2, promesa3])
.then((resultados) => {
console.log(resultadost); // Salida: [3, "¡Hola!", 42]
})
.catch((error) => {
console.error("Una de las promesas falló:", error);
});
const promesaLenta = new Promise((resolve) => setTimeout(resolve, 500, 'Lenta'));
const promesaRapida = new Promise((resolve) => setTimeout(resolve, 100, 'Rápida'));
Promise.race([promesaLenta, promesaRapida])
.then((resultado) => {
console.log(resultado); // Salida: "Rápida"
});
const promesaConError = new Promise((resolve, reject) => {
reject("Hubo un error");
});
promesaConError
.then((resultado) => {
console.log(resultado);
})
.catch((error) => {
console.error(error); // Salida: Hubo un error
});
+——————+ +——————+ | Subject |<————->| Observer | +——————+ +——————+ | +attach(o:Observer)| | +update() | | +detach(o:Observer)| +——————+ | +notify() | | +getState() | | +setState() | +——————+ | | +———————+ | ConcreteSubject | +———————+ | +getState() | | +setState() | +———————+ | | +———————+ | ConcreteObserver | +———————+ | +update() | +———————+
Implementación del Patrón Observer en JavaScript
class Subject {
constructor() {
this.observers = [];
}
attach(observer) {
this.observers.push(observer);
}
detach(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify() {
this.observers.forEach(observer => observer.update(this));
}
}
class Observer {
update(subject) {
console.log(`Estado actualizado: ${subject.getState()}`);
}
}
class ConcreteSubject extends Subject {
constructor() {
super();
this.state = 0;
}
getState() {
return this.state;
}
setState(state) {
this.state = state;
this.notify(); // Notificar a los observadores sobre el cambio de estado
}
}
class ConcreteObserver extends Observer {
constructor(name) {
super();
this.name = name;
}
update(subject) {
console.log(`${this.name} ha recibido la actualización: ${subject.getState()}`);
}
}
const subject = new ConcreteSubject();
const observerA = new ConcreteObserver('Observer A');
const observerB = new ConcreteObserver('Observer B');
subject.attach(observerA);
subject.attach(observerB);
subject.setState(1); // Salida: Observer A ha recibido la actualización: 1
// Observer B ha recibido la actualización: 1
subject.detach(observerA);
subject.setState(2); // Salida: Observer B ha recibido la actualización: 2
import { Observable } from ‘rxjs’;
const miObservable = new Observable(subscriber => { subscriber.next(‘Hola’); subscriber.next(‘Mundo’); subscriber.complete(); });
miObservable.subscribe({ next(x) { console.log(x); }, complete() { console.log(‘Completado’); } });
- Salida Esperada:
```consola
Hola
Mundo
Completado
const subscription = miObservable.subscribe({ next(x) { console.log(x); } });
// Para cancelar la suscripción subscription.unsubscribe();
## peradores Comunes en Programación Reactiva
- RxJS incluye una amplia variedad de operadores que permiten manipular flujos de datos.
1. map
- Transformar los datos emitidos por un observable.
```javascript
import { map } from 'rxjs/operators';
const numeros = [1, 2, 3];
const numerosObservable = from(numeros).pipe(
map(num => num * 2)
);
numerosObservable.subscribe(console.log); // Salida: 2, 4, 6
import { filter } from 'rxjs/operators';
const numerosFiltrados = from(numeros).pipe(
filter(num => num > 1)
);
numerosFiltrados.subscribe(console.log); // Salida: 2, 3
import { combineLatest } from 'rxjs';
const observable1 = of(1, 2, 3);
const observable2 = of('A', 'B', 'C');
combineLatest([observable1, observable2]).subscribe(console.log);
// Salida: [3, "C"] (últimos valores de ambos observables)
import { Observable } from 'rxjs';
const miObservable = new Observable(subscriber => {
subscriber.next('Hola');
subscriber.next('Mundo');
subscriber.complete();
});
import { of } from 'rxjs';
const numeros$ = of(1, 2, 3, 4, 5);
import { from } from 'rxjs';
const array$ = from([10, 20, 30]);
import { interval } from 'rxjs';
const contador$ = interval(1000); // Emite un número cada segundo
const subscription = miObservable.subscribe({
next(x) { console.log(x); },
complete() { console.log('Completado'); }
});
// Para cancelar la suscripción
subscription.unsubscribe();
import { map } from 'rxjs/operators';
numeros$.pipe(
map(num => num * 2)
).subscribe(console.log); // Salida: 2, 4, 6, 8, 10
import { filter } from 'rxjs/operators';
numeros$.pipe(
filter(num => num > 2)
).subscribe(console.log); // Salida: 3, 4, 5
import { merge } from 'rxjs';
const obs1$ = of('A', 'B');
const obs2$ = of('C', 'D');
merge(obs1$, obs2$).subscribe(console.log); // Salida: A, B, C, D
ng new buscador-app
cd buscador-app
ng serve
Crear un servicio que simule la búsqueda de datos. Este servicio se encargará de hacer “búsquedas” en un conjunto de datos estáticos.
Crear un servicio llamado api.service.ts:
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ApiService {
private datos = ['Angular', 'React', 'Vue', 'Svelte', 'Ember'];
buscar(termino: string) {
const resultados = this.datos.filter(item =>
item.toLowerCase().includes(termino.toLowerCase())
);
return of(resultados).pipe(delay(500)); // Simula un retraso en la respuesta
}
}
Crear un componente llamado busqueda.component.ts:
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, switchMap } from 'rxjs/operators';
import { ApiService } from './api.service';
@Component({
selector: 'app-busqueda',
template: `
<input [formControl]="searchControl" placeholder="Buscar..."/>
<ul>
<li *ngFor="let resultado of resultados"></li>
</ul>
`,
styles: [`
input {
margin: 20px 0;
padding: 10px;
width: 300px;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 5px 0;
}
`]
})
export class BusquedaComponent implements OnInit {
searchControl = new FormControl();
resultados: string[] = [];
constructor(private apiService: ApiService) {}
ngOnInit() {
this.searchControl.valueChanges.pipe(
debounceTime(300), // Espera 300ms antes de buscar
switchMap(value => this.apiService.buscar(value)) // Llama al servicio de búsqueda
).subscribe(resultados => {
this.resultados = resultados; // Actualiza los resultados en la vista
});
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { BusquedaComponent } from './busqueda.component'; // Importa el componente
@NgModule({
declarations: [
AppComponent,
BusquedaComponent // Declara el componente
],
imports: [
BrowserModule,
ReactiveFormsModule // Agrega el módulo de formularios reactivos
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
<h1>Buscador en Tiempo Real</h1>
<app-busqueda></app-busqueda>
ng serve