npat89
npat89

Reputation: 263

What's the difference between map and pluck in RxJS?

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

Answers (5)

Simon_Weaver
Simon_Weaver

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

GBra 4.669
GBra 4.669

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

maxime1992
maxime1992

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

mgm87
mgm87

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

Jonny Rathbone
Jonny Rathbone

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

Related Questions