Reputation: 568
I have a simple JSON file which returns an array of objects in format:
[
{
"id": 1,
"url": "file/abc.txt"
},
{
"id": 2,
"url": "file/def.txt"
}
]
I am accessing the service as given below:
this.http.get("json-url")
.map((response) => response.json())
.filter((file) => file.id === 1)
It doesn't work anything. However if I use mergeMap instead, it works fine.
this.http.get("api-url")
.mergeMap((response) => response.json())
.filter((file) => file.id === 1)
I have used map operator earlier and it worked. However it is not working here. Please let me know if I am mistaking anything while using map operator.
Please note- I am using angular 6.
Upvotes: 0
Views: 2033
Reputation: 1705
Important to understand here is that this.http.get("json-url")
returns an observable. It won't be executed until you subscribe. You must subscribe to send the request.
this.http.get("json-url")
.map((response) => response.json())
.filter((file) => file.id === 1)
.subscribe(theResultAfterMapAndFilter => console.log(theResultAfterMapAndFilter));
The reason why mergeMap
works is that it subscribes to the source observable internally (if I'm not mistaken).
Upvotes: 1
Reputation: 39482
If you're running Angular 6, it's really recommended to use HttpClient
as Http
is deprecated. Now since you'd be using HttpClient
you won't need to call .json
method on the response
as that is something that HttpClient
takes care of implicitly.
Also, since Angular 6 uses Rxjs 5.5 or later, you can't directly chain the operators like map
and pipe
to an Observable
. You'll have to call the pipe
function on an Observable
value and add the list of operators that you want to you separated by a ,
.
import { HttpClient } from '@angular/common/http';
import { map, filter } from 'rxjs/operators';
...
constructor(private http: HttpClient) {}
...
return this.http.get("json-url")
.pipe(filter((file) => file.id === 1));
Here, I'm returning the Observable
so that I can subscribe
to it from the place I'm calling the function that is wrapping this piece of code.
To make sure that HttpClient
works correctly, you'll also have to import HttpClientModule
in your @NgModule
file and add it to the imports
array.
Upvotes: 1
Reputation: 3651
I have an answer for why map
isn't working, but i'm not entirely sure why mergeMap
is working. The object returned from response.json()
is any list. So the filter
should handle the full list. Not the individual elements of the list. The list has not property of id
so nothing matches. Even though the parameter in filter
is called file
, it should be files
. I believe the following will work with map:
this.http.get("json-url")
.map((response) => response.json())
.filter((files) => files.filter((file)->file.id === 1));
However, you would get a list back. If you really want a single file, you could add in another map:
this.http.get("json-url")
.map((response) => response.json())
.filter((files) => files.filter((file)->file.id === 1))
.map(files=> files[0]);
With all of that said, I think the reason mergeMap
worked might be some older quirk of rxjs. My unverified guess is that list returned from the anonymous function is being converted into an observable by mergeMap
. That seems a bit fishy, but could be possible. The older rxjs API seemed to try to make things work even if it probably shouldn't.
Upvotes: 0