angularrxjs

Manipulate Observable data prior to subscribe method call


I've been using Angular with RxJS for about a year and a half now. I feel pretty comfortable in most areas, but I'm struggling a bit with RxJS. Several times now I've found myself wanting to manipulate or change the data being returned from an Observable (almost always an HTTP call), before the corresponding subscribe method is called on the Observable. Googling always seems to point to some combination of pipe, map, etc. but I'm having trouble understanding which combination will work best for me.

For example, I've got an API method which returns a config object, with a specific sub-object.

{
  brand: 'Big Lug',
  options: {
    token: true,
    security: false,
    certificate: true,
  },
  ...
}

I'd like to intercept this method call and return a completely different output:

if (options.token && !options.certificate && !options.security) {
   return 'FOO';
} else if(options.security && options.certificate) {
   return 'BAR';
} else if(options.token && options.certificate) {
   return 'BAZ';
}

In other words I don't want to return an object at all, I want to return a single string. I'd like to perform this change in the service, so that anytime a component calls this method, it receives the desired response, like so:

this.myService.myMethod().subscribe(
    theString => {
        // theString is either FOO, BAR, or BAZ
    }
)

None of the RxJS methods seem to allow for logic inside their callbacks. The closest I've found appears to be switchMap, but the body doesn't seem to allow for logic. The examples I've seen just show a single statement.


Solution

  • For your scenario, you should look for map RxJS operator instead of switchMap.

    Reasons:

    1. Pure/one-time change the result of the observable.
    2. Your scenario is not cancelling, flattening or dealing with multiple observable streams (complex).
    myMethod() {
      return /* Your Observarble instance for API call */
        .pipe(
          map(response => {
            const { token, security, certificate } = response.options;
    
            if (token && !certificate && !security) {
              return 'FOO';
            } else if (security && certificate) {
             return 'BAR';
            } else if (token && certificate) {
             return 'BAZ';
            } else {
              return 'DEFAULT';
            }
        })
      );
    }