0

I think I am missing something here, since I find using Angular http.get with pipe(map) from RXJS quite counter intuitive:

The backend returns an array of simple objects (see Unifiedparams interface below). I want to extract an Observable<String[]> and pass it on to the app.component.html, where I use *ngFor="let param of params$ | async" to build a dropdown.

I can't seem to be able to access the name attribute without nested maps although the returned json is a single dimension array.

fetchParams(): Observable<String[]>{
    const result = this.http.get<unifiedParam[]>('http://localhost:5000/getparams');
    const params:Observable<String[]> = result.pipe(map(unifiedParams => res.map(unifiedParam=>unifiedParam.name)));
    return params;
}

This seems to indicate that the Observable is an array itself but using this.http.get<unifiedParam> and rows:Observable<String> respectively results in rows being empty:

fetchParams(): Observable<String>{
    const result = this.http.get<unifiedParam>('http://localhost:5000/getparams');
    const params:Observable<String> = result.pipe(map(unifiedParam=> unifiedParam.name)));
    params.pipe(tap(console.log)); //doesn't print anything
    return params;   
}

So my question here is if using Observable<UnifiedParam[]> and .pipe(map(res=>map(el=>el.name) is the way to go.

Thanks!

Update: Forgot the interface :)

interface unifiedParam { name: String, source: String };

Update 2: To clarify what puzzles me: Why do I need the outer map() function. Isn't map() defined for arrays?

4
  • Where is the interface for Unifiedparams? Commented Jul 8, 2019 at 13:14
  • @robert1 sorry forgot to add it Commented Jul 8, 2019 at 14:42
  • answer updated to explain a little more why 2 map functions and differences. Hope it helps. Commented Jul 8, 2019 at 14:58
  • params.pipe(tap(console.log)); not working because you are not subscribing to it, you have to change it like: return params.pipe(tap(console.log)) Commented Jul 8, 2019 at 15:28

2 Answers 2

1

I'm not fully sure to understand your question/need.

If your backend api returns an array of UnifiedParam model, so UnifiedParam[], and you need to retrieve an array of names, so string[], and if your model looks like :

UnifiedParam {
  ...
  name: string
  ...
}

so your first approach is fine.

Just a little refactoring of your code:

fetchParams(): Observable<String[]> {
  return this.http.get<UnifiedParam[]>('http://localhost:5000/getparams').pipe(
    map(unifiedParams => unifiedParams.map(unifiedParam => unifiedParam.name)) 
  )
}

My advice is also to correctly type your models, and also use comprehensive variable/argument names. (for instance, inside map operator : unifiedParams...).

It will help to keep code clear and maintainable.

Updated

In your code, there are 2 map functions :

  • one is an array map function, to iterate on each item of an array, and transform it by returning a "projection" of it, or any other new object.
  • second one, is an Observable operator, which means: for every value emitted in the stream, transform it to another value.

So here, in other words:

  • invoke an Get Http request to retrieve a list of UnifiedParam.
  • when server reply, receive a stream (Observable) with only one value (array of UnifiedParam) and then this stream will complete itself.
  • for each value in the stream (so the only one), we transform it (the array of UnifiedParam) to a new array of names.

Hope it's more clear with this update.

Sign up to request clarification or add additional context in comments.

1 Comment

Thx @Thierry Falvo for your suggestions.
0

You can transform your array to an Observable and flatmap it, then use only one map operator (from Observable this time) :

fetchParams(): Observable<String> {
  return this.http.get<UnifiedParam[]>('http://localhost:5000/getparams')
             .pipe(
                 mergeMap(unifiedParams => from(unifiedParams)),
                 map(unifiedParam => unifiedParam.name) 
              )
}

Notice that you'll not receive an Observable<String[]> but directly Observable<String>, i don't know if this suits you

1 Comment

This is interesting, however "NgFor only supports binding to Iterables such as Arrays." Also fromArray seems to be obsolete, its "from" now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.