Akkusativobjekt Akkusativobjekt - 26 days ago 16
TypeScript Question

How to drop the response of an Observable

With the help of Observable.timer(0, 1000) I am making continuous requests to my server in a defined time pattern. After I processed the content of the response it is possible under special conditions and depending on the previous response that I need to drop the response and therefore do not pass it to the subscriber of the service:

@Injectable()
export class LoggerService {
constructor(private http: Http) { }
private apiURL = 'assets/file.json';

getList() {
return Observable.timer(0, 1000)
.concatMap(() => this.http.get(this.apiURL))
.map(this.extractData)
.catch(this.handleError););
}
private extractData(res: Response) {
var fooot = new Foo();
fooot.fillFromJSON(JSON.stringify(res.json()));
if(fooot.getProperty()){
//DROP IT
}
return fooot;
}

private handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}


The
getList()
method is then called from
ngOnInit
of a component.
At the moment there are two possible solutions I can think of, buy maybe there is a better/clearer approach to solve this problem:


  1. If I have to drop the response I create a special object which is recognized by the subscriber of
    getList()
    and then specifically handled. But this solution would be very ugly because the dropped response leaves my service and I need to extra write code outside of the service to handle this case.

  2. I throw an exception when I have to drop the response. Then the exception is caught, recognized (to differ it from other cases) and then dropped without any notice/output. Afterwards the observable is restarted. The advantage of this approach is that the observable which should be dropped to not leave the service, but I do not like the usage of exceptions in this case for the control flow.



I tried both solutions and they are working, but I hope there are some better approaches.

Answer

I ended up using distinctUntilChanged to archive my goal:

getList() {
    return Observable.timer(0, 1000)
      .concatMap(() => this.http.get(this.apiURL)
      .distinctUntilChanged(null, x => x.json().info[1].value)
      .map(this.extractData)
      .catch(this.handleError);
  }

Therefore if the current and last response share the same specific value, the newest response is dropped. I guess my question was not clear enough and I did not mention that the decision to drop a response depends on the previous one.

A downside of this approach is that the response have to be parsed twice, but I guess that cannot be avoided. It would be nice to know if the json approch is faster than a complete string compare of the result (body).

If the decision to drop a response only depends on the current response, I would recommend to use a filter.

Comments