Jamal James
Jamal James

Reputation: 91

rxjs - understand observable and observer

I can't get my head around observable and observer (rxjs), i understand that observable can dispatch the messages to observer, and observer subscribe to observable, but I dont know how to setup this?

Lets say I would like to request URL, first time the user call "loadData", the data is loaded from http request, and saved locally inside the class, next time the user call "loadData", we dont want to load from http, but get the data locally, but I would like to use the same code "loadData", and it should return Observer, so the developed don't know where and how the data is loaded!

let data = [];
function loadData():Observer {
   var observer = new Observer();
   if (data.length > 0) {
      var observable = new Observable.from(data);
      observable.add(observer);
      observable.notify();
   } else {
      var observable = this.http.get("data.json");
      observable.add(observer);
      observable.readyData( (data) => { 
         this.data = data; 
         observable.notify(); 
      };
  }
}

var observer = loadData();
observer.dataComing((data) => console.log(data));

Any explanation or link to any page would be great, I understand map filter reduce in Array etc, and also the observer pattern which is easy, but not RXJS way, it's very confusing!

Thank you very much!

Upvotes: 4

Views: 3700

Answers (1)

Thierry Templier
Thierry Templier

Reputation: 202138

Here is sample of observer / observable:

var obs = Observable.create((observer) => {
  setTimeout(() => {
    observer.next('some event');
  }, 1000);
});

obs.subscribe((event) => {
  // The event is received here
});

The observer is used to trigger an event and the observable to receive it in short. Most of time, the observer is intervalle used. For example by the HTTP support of Angular2

Here are some links regarding reactive programming:

For your particularly use case, you could use this:

loadData(url:string):Observable {
  if (this.cachedData) {
    return Observable.of(this.cachedData);
  } else {
    return this.get(...).map(res => res.map()).do((data) => {
      this.cachedData = data;
    });
  }
}

Edit

I would refactor your code this way:

@Injectable()
export class LoungesService {
  constructor(private http:Http) {
    this.loungesByCity = {};
  }

  getLoungesByCity(city:City):Observable<any> {
    if (this.loungesByCity && this.loungesByCity[city.id]) {
      return Observable.of(this. loungesByCity[city.id]);
    } else {
      return this.http.get("lounges.json")
          .map(res => <Lounge[]> res.json().data)
          .map((lounges) => {
            return lounges.filter((lounge) => lounge.city_id === city.id);
          })
          .do(data => this.loungesByCity[city.id] = data);
  }
}

Note that LoungesService must be defined as shared service when bootstrapping your application:

bootstrap(AppComponent, [ LoungesService ]);

Upvotes: 4

Related Questions