TORNAR

Esdeveniments en Angular2

3 min de lectura

Durant la migració del component feed, vaig trobar algunes línies que no sabia com codificar en Angular 2. El següent codi és un extracte del codi del que estic parlant:

if (!feed.isLocalScreen) {
// Fins que s'assoleixi aquest temps d'espera, la notificació "estàs silenciat"
// no es mostrarà de nou
var mutedWarningTimeout = now();
scope.$on('muted.byRequest', function() {
mutedWarningTimeout = secondsFromNow(3);
MuteNotifier.muted();
});
scope.$on('muted.byUser', function() {
// Restablir el temps d'espera d'advertència
mutedWarningTimeout = now();
});
scope.$on('muted.Join', function() {
mutedWarningTimeout = now();
MuteNotifier.joinedMuted();
});
scope.$watch('vm.feed.isVoiceDetected()', function(newVal) {
// Mostrar advertència només si està silenciat (comprovar false, undefined significa
// encara connectant) i s'ha assolit el temps d'espera
if (newVal && feed.getAudioEnabled() === false && now() > mutedWarningTimeout) {
MuteNotifier.speaking();
mutedWarningTimeout = secondsFromNow(60);
}
});
}

Com pots veure en el fragment, si la condició és veritable llavors la directiva escolta esdeveniments de tipus muted.byRequest, muted.byUser i muted.Join. El codi que involucra aquests esdeveniments és fàcil, sense cap tipus de complexitat (per ara ignorem el $watch).

Però, espera un minut, he llegit la documentació d'Angular 2 com cent vegades i no recordo res sobre "esdeveniments" amb estil Angular 1.X. Això és perquè no existeix. Angular 2 no té una forma de fer esdeveniments com en Angular 1, així que he de trobar una solució. Després de buscar una solució, vaig trobar aquesta entrada al blog de laco.

Broadcaster

Bàsicament, la idea és fer un servei que implementi el $broadcast i $on un mètode com teníem en $rootScope. Per fer això utilitzem Observables, molt importants en Angular 2, i per a aquest cas, utilitzem un Subject.

import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
interface BroadcastEvent {
key: any;
data?: any;
}
export class Broadcaster {
private _eventBus: Subject<BroadcastEvent>;
constructor() {
this._eventBus = new Subject<BroadcastEvent>();
}
broadcast(key: any, data?: any) {
this._eventBus.next({ key, data });
}
on<T>(key: any): Observable<T> {
return this._eventBus
.asObservable()
.filter(event => event.key === key)
.map(event => <T>event.data);
}
}

Així que, ara podem començar a utilitzar esdeveniments com en l'exemple:

// child.ts
@Component({
selector: 'child'
})
export class ChildComponent {
constructor(private broadcaster: Broadcaster) {
}
registerStringBroadcast() {
this.broadcaster.on<string>('MyEvent')
.subscribe(message => {
...
});
}
emitStringBroadcast() {
this.broadcaster.broadcast('MyEvent', 'some message');
}
}

Com vaig resoldre el problema?

No ho vaig fer. Aquests esdeveniments són només per mostrar a l'usuari finestres emergents d'informació sobre quan està silenciat, així que no és una característica crítica. Per ara aquests esdeveniments es disparen i escolten en diferents components, i alguns d'ells encara implementats en Angular 1.4.

Aquesta és una solució que vull compartir amb tu, però no estic segur de si aquesta serà la forma que utilitzaré per resoldre el problema. Perquè aquests esdeveniments probablement no seran necessaris quan reimplementi el MuteNotifier.