observer-ax
Version:
Patrón observable, event Bus.
107 lines (95 loc) • 3.65 kB
text/typescript
import { SubjectObserver } from './Subject';
import { Observer } from './Observer';
import { ItemBus } from '../models/Item.model';
import { NotifyObject } from '../models/NotifyObject.model';
/**
* The Subject owns some important state and notifies observers when the state
* changes.
*/
export class ConcreteSubjectObserver implements SubjectObserver {
/**
* @type {ItemBus[]} Data to notify
*/
private _items: ItemBus[] = [];
private _receivers: { [key: string]: Observer[] } = {};
constructor(private defaultTriesCount: number = 3) { }
protected getTopicReceivers(topic: string = 'ALL'): Observer[] {
if (!this.receivers[topic]) {
return [];
}
return this.receivers[topic];
}
protected retryPublish(topic: string, item: NotifyObject, receiver: Observer, tries: number = 1) {
for (var i = 0; i < tries; i++) {
try {
receiver.update(item, { topic: topic, pendingItems: this._items.length });
break;
} catch (error) {
console.error(error);
}
}
}
public async notifyNow(item: ItemBus): Promise<void> {
if (item.tries === 0) {
item.tries = this.defaultTriesCount;
}
const receivers = this.getTopicReceivers(item.topic);
receivers.map((receiver: Observer) => new Promise(resolve => resolve(this.retryPublish(item.topic, item.data, receiver, item.tries))));
}
public async notify(): Promise<void> {
while (this._items.length > 0) {
const item = this._items.shift() as ItemBus;
const receivers = this.getTopicReceivers(item.topic);
console.log(receivers);
receivers.map((receiver: Observer) =>
new Promise(resolve =>
resolve(this.retryPublish(item.topic, item.data, receiver, item.tries))));
}
}
public attach(receiver: Observer, topic: string = 'ALL') {
if (!this.receivers[topic]) {
this.receivers[topic] = [];
}
const isExist = this.receivers[topic].includes(receiver);
if (isExist) {
return console.log('Subject: Observer has been attached already.');
}
this.receivers[topic].push(receiver);
}
public detach(receiver: Observer, topic: string = 'ALL') {
if (!this.receivers[topic]) {
return;
}
const observerIndex = this.receivers[topic].indexOf(receiver);
if (observerIndex === -1) {
return console.log('Subject: Nonexistent observer.');
}
this.receivers[topic] = this.receivers[topic].filter(item => item !== receiver);
}
asObserver(): Observer {
const clazz = new class Concrete implements Observer {
data: NotifyObject;
options?: any;
callback: any;
update(data: NotifyObject, options?: any) {
this.data = data;
this.options = options;
if (this.callback) this.callback(this.data.data, this.options);
}
subscribe(callback: (data: any, options?: any) => any) {
this.callback = callback;
}
}();
this.attach(clazz);
return clazz;
}
get receivers(): any {
return this._receivers;
}
set items(values: ItemBus[]) {
this._items.push(...values);
}
set item(value: ItemBus) {
this._items.push(value);
}
}