Reputation: 263
I am trying to understand the difference between map and pluck transformational operators in RxJS.
Can anyone help me with this?
Upvotes: 23
Views: 18210
Reputation: 146218
The docs say
Pluck : Like map, but meant only for picking one of the nested properties of every emitted object.
Therefore, let's say you have
[
{ name: 'Joe', age: 30, job: { title: 'Developer', language: 'JavaScript' } },
{ name: 'Sarah', age: 35 }
]
and you want a list of all job titles. pluck
returns
"Developer" , undefined
Using map
would be kind of a pain (because of the nullability of job
), but with 'pluck' you can write pluck('job', 'title')
and it will traverse the tree looking for job.title
- and won't fail if job
is null.
Example taken from : https://www.learnrxjs.io/learn-rxjs/operators/transformation/pluck
https://jsfiddle.net/btroncone/n592m597/
P.S: Please note that pluck
has been deprecated
Deprecation Notes
Use map and optional chaining: pluck('foo', 'bar') is map(x => x?.foo?.bar). Will be removed in v8.
Upvotes: 22
Reputation: 1679
Stop using pluck!
Pluck
is now planned to be removed in RxJS v8.
Do you know what is the reason?
Because after the addition of the optional chaining operator in JS, it's essentially, just a weak version of Map
.
So what's the difference between the two?
Both are used to "transform" the data that is going to be emitted.
Map
can be used to... map an observable emission (like we do in JS with Array.prototype.map
), while Pluck
is used to select/pick a property to emit (without having to emit properties that we don't care for, hence improving the performance).
But even before the optional chaining operator, you could just map the properties instead of plucking them. The result & performance were/are about the same.
pluck('prop')
is just a shorthand for:
map(x => x.prop)
Well, then what was the reason behind the implementation of Pluck
?
It was basically implemented to achieve path traversal safety, meaning you could try to pluck a nested property without getting the error (that Map would throw) if the property is not defined:
pluck('foo', 'bar', 'baz'); // no error if foo is not defined
map(x => x.foo.bar.baz) // error if foo is not defined
With optional chaining, this advantage doesn't exists anymore, since we can just do this:
map(x => x?.foo?.bar?.baz)
This is the main reason why the Pluck
operator is going to be deprecated and removed in the future.
Another important reason is TS typing for pluck is quite complex and not as robust as the map operator.
Got that info in GitHub:
The commit of Pluck
deprecation is almost one year old but I still don't see any warning of future deprecation in the docs, hence I am posting here since I think it's a good thing to know. I already stopped plucking for this reason.
Upvotes: 18
Reputation: 23813
As @mgm87 said, you can perform an operation with map
.
On the opposite, pluck
is just taking a value.
For example, with map you could do something like that:
this.http.get('...some api url to get a user...')
.map(response => response.json())
.map(user => user.age > 18 ? 'major': 'minor')
.do(isMajorOrMinor => console.log(isMajorOrMinor))
So you can manipulate your data down the chain even conditionally.
BUT, for me one of the big differences is that map is typed
.
Which means if you have some data let say:
interface IUser {
name: string;
age: number;
dogs: IDog[];
}
And you receive at some point a user, from which you want to get his dogs:
user$
.map(user => user.dogs)
.do(dogs => ...) // here, you do NOT need to precise (dogs: IDog[]) because Typescript will make a type inference
And that's why I'm always using map even to just "pluck" some data.
Upvotes: 12
Reputation: 904
Map can perform an operation on each emitted value. http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-map https://www.learnrxjs.io/operators/transformation/map.html
// value from observable = 10
map(x => 10*x)
// value from map = 100
Pluck simply picks one of the nested properties of each emitted value. http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-pluck https://www.learnrxjs.io/operators/transformation/pluck.html
// value from observable = {p = 10, w = 100}
pluck('p')
// value from pluck = 10
Upvotes: 1
Reputation: 179
They are very similar, but as I understand it, map works with an array whereas pluck takes the values from an object.
This is the place to go for specifics.
Upvotes: -4