6

I am fairly new to rxjs.

I tried to create a function that runs a angular 2 http request like that:

syncFromApi$() {

  // create Headers
  ...

  let ob$ = this.http.post(
    CONFIG_APP.apiEndpoint + '/sync/app',
    '',
    { headers: headers }
  )
  .map((response:Response) => {
    return Observable.of({type: "success", payload: response.json()});
  })
  .catch(function (err:Response) {
    return Observable.of({type: "error", payload: err.json()});
  });

  return ob$;
}

In short, when having success, I am returning an Object which indicates, if the request was successful. After that I want to switch map depending on the returned object:

let o$ = syncFromApi$()
  .switchMap((value) => {
    console.log("value", JSON.stringify(value, null, 0));
    if (data.type === 'success') {
      return Observable.of(1);
    } else if (data.type === 'error') {
      return Observable.of(2);
    }
  });

And here comes the problem I face. The console.log(...) outputs a object like this:

value, {"_isScalar": true, "value": THIS_IS_WHAT_I_NEED_AS_VALUE, "scheduler": null}

But I need only the object I returned with the syncFromApi$ function.

Can anyone explain to me, if I am using observable.of() in the wrong manner?

I tried observable.of(1) and it returns 1 as value. If I use a object (observable.of({ type: "myType", message: "myMessage" })), it returns an object wrapping the object I need with the keys "_isScalar", "value" and "scheduler".

Thanks in advance.

Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
divramod
  • 1,454
  • 2
  • 20
  • 35
  • 1
    Why do you return an Observable from your mapping function, and not just the object? You don't want an Observable of Observables. – JB Nizet May 02 '16 at 22:07
  • i later want to subscribe to the chain of observables – divramod May 02 '16 at 22:11
  • map transform an observable of x into an observable of y thanks to a function transforming x into y. No need to wrap y into an Observable. – JB Nizet May 02 '16 at 22:13
  • if i remove Observable.of() around the object in the catch block, my typescript compiler complains with the following message: ```app/app/services/state.ts|116 col 14 error| Argument of type '(err: Response) => { type: string; payload: any; }' is not assignable to parameter of type '(err: any, caught: Observable<{ type: string; payload: any; }>) => Observable<{}>'. Type '{ type: string; payload: any; }' is not assignable to type 'Observable<{}>'. Property '_isScalar' is missing in type '{ type: string; payload: any; }'. ``` – divramod May 02 '16 at 22:19
  • What's in catch looks OK to me. What's in map doesn't. – JB Nizet May 03 '16 at 05:53

1 Answers1

15

Your problem is in your map operator:

let ob$ = this.http.post(
  CONFIG_APP.apiEndpoint + '/sync/app',
  '',
  { headers: headers }
)
.map((response:Response) => {
  return {type: "success", payload: response.json()}; // <----
})

You need to return an object not an observable. The map operator uses the object like it is and doesn't project the returned observable into the observable chain.

If you want to return Observable.of for some reasons, you need to use the flatMap operator instead:

let ob$ = this.http.post(
  CONFIG_APP.apiEndpoint + '/sync/app',
  '',
  { headers: headers }
)
.flatMap((response:Response) => {
  return Observable.of({type: "success", payload: response.json()});
})

That's fine for the catch operator since it expects an observable to be returned into its associated callback.

Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360