The following code is an extract of a small library I wrote. Full code is available here.

My question is about the following function. I added comments on each state. I'm wondering if I could do things easier, I've the feeling I'm using too many flatMap:

  * request
  * @param {string} method
  * @param {RxRestItem|FormData|URLSearchParams|Body|Blob|undefined|Object} [body]
  * @returns {Observable<RxRestItem|RxRestCollection>}
request(method: string, body?: BodyParam): Observable<RxRestItem|RxRestCollection> {
  let requestOptions = {
    method: method,
    headers: <Headers> this.requestHeaders,
    //this is just a function that transforms a Body to json if needed
    body: this.requestBodyHandler(body)

  let request = new Request(this.URL + this.requestQueryParams, requestOptions);

  //let's start from our Request object
  return Observable.of(request)

  //here, we call functions that can alter the request, think middlewares (see below for this method)

  //now we have the final request, we do a `fetch` on it
  .flatMap(request => fetch(request))

  //Transform the response to a javascript object
  .flatMap(body => Observable.fromPromise(this.responseBodyHandler(body)))

  //Here the library transforms object to internal types
  .map(e => {
    if (!Array.isArray(e)) {
      let item: RxRestItem

      if (this instanceof RxRestItem) {
        item = this
        item.element = e
      } else {
        item = new RxRestItem(this.$route, e)

      item.$fromServer = true
      return item

    return new RxRestCollection(this.$route, e.map(e => {
      let item = new RxRestItem(this.$route, e)
      item.$fromServer = true
      return item

  //response middlewares

  .catch(body => {
    //this was a real error
    if (!(body instanceof Response)) {
      return Observable.throw(body)

    //error interceptors
    return Observable.of(body)

The middleware function feels complicated too, it takes an array of functions and apply them (like a reduce). However, this interceptor function can return a Promise, an Observable or a changed value:

  * expandInterceptors
  * @param {RequestInterceptor[]|ResponseInterceptor[]|ErrorInterceptor[]} interceptors
  * @returns {Observable<any>} fn
expandInterceptors(interceptors: RequestInterceptor[]|ResponseInterceptor[]|ErrorInterceptor[]) {
  return function(origin: any): Observable<any> {
    return (<any>interceptors).reduce(
      (obs: Observable<any>, interceptor: any) =>
        obs.concatMap(value => {
          let result = interceptor(value)
          if (result === undefined) {
            return Observable.of(value)

          if (result instanceof Observable || result instanceof Promise) {
            return result

          return Observable.of(result)

Do you think that I'm doing things the right way? Can this code be simplified?

I'm new to reactive programming and still trying to understand some of it's core concepts!


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.