RxJS 5 is a ground-up rewrite of RxJS that actually began development when RxJS was in 2.0. This new version of RxJS had three basic goals:
- Better performance
- Better debugging
- Compliance with the ES7 Observable Spec
Meeting the above goals meant breaking changes to the RxJS API, and a complete rewrite means that we had opportunity to change/fix/correct things we've wanted to correct about RxJS in general.
They are similar to other language implementations of ReactiveX (e.g. RxJava).
RxJS 4 | RxJS 5 | remarks |
---|---|---|
Observer |
Subscriber implements Observer |
Observer is an interface now |
IDisposable |
Subscription |
Subscription is a class, not an interface. |
Due to wanting to comply with the ES7 Observable Spec (goal 3 above), the Observer interface (as implemented by Observers and Subjects alike) has changed.
observer.onNext(value)
->observer.next(value)
observer.onError(err)
->observer.error(err)
observer.onCompleted()
->observer.complete()
So what was once subject.onNext("hi")
is now subject.next("hi")
.
To meet the Observable spec (goal 3) dispose
had to be renamed to unsubscribe
.
var subscription = myObservable.subscribe(doSomething);
// RxJS 4: subscription.dispose();
subscription.unsubscribe();
In RxJS 4, there was the idea of a CompositeSubscription
. Now all Subscriptions are "composite".
Subscription objects have an add
and remove
method on them useful for adding and removing subscriptions
enabling "composite" subscription behavior.
RxJS 4 | RxJS 5 |
---|---|
amb |
race |
and |
No longer implemented |
asObservable |
Exists on Subject only |
average |
No longer implemented |
bufferWithCount |
bufferCount |
bufferWithTime |
bufferTime |
concat |
concat |
concatAll |
concatAll |
concatMap |
concatMap |
concatMapObserver |
No longer implemented |
controlled |
No longer implemented |
delaySubscription |
No longer implemented |
do |
do |
doAction |
do |
doOnCompleted |
do(null, null, fn) |
doOnError |
do(null, fn) |
doOnNext |
do(fn) |
doWhile |
No longer implemented |
extend |
No longer implemented |
flatMapFirst |
exhaustMap |
flatMapLatest |
switchMap |
flatMapWithMaxConcurrent |
mergeMap or flatMap (alias) |
flatMap |
mergeMap or flatMap (alias) |
fromCallback |
bindCallback |
fromNodeCallback |
bindNodeCallback |
groupByUntil |
groupBy(keySelector, elementSelector, durationSelector) |
groupJoin |
No longer implemented |
includes(v) |
.first(x => x === v, () => true, false) |
indexOf(v) |
.map((x, i) => [x === v, i]).filter(([x]) => x).map(([_, i]) => i).first() |
join |
No longer implemented |
jortSortUntil |
No longer implemented |
jortSort |
No longer implemented |
just(v) or just(a, b, c) |
of(v) , of(a, b, c) |
lastIndexOf |
.map((x, i) => [x === v, i]).filter(([x]) => x).map(([_, i]) => i).last() |
manySelect |
No longer implemented |
map(fn) |
map(fn) |
map(value) |
mapTo(value) |
maxBy(fn) |
scan((s, v, i) => { let max = Math.max(s.max, fn(v, i)); return { max, value: max === s.max ? s.value : v }; }, { max: null, value: undefined }).last(x => x.max !== null, x => x.value) |
minBy(fn) |
scan((s, v, i) => { let min = Math.min(s.min, fn(v, i)); return { min, value: min === s.min ? s.value : v }; }, { min: null, value: undefined }).last(x => x.min !== null, x => x.value) |
of |
of |
ofObjectChanges |
No longer implemented |
pausableBuffered |
No longer implemented |
pausable |
No longer implemented |
pluck |
pluck |
publishLast |
publishLast |
publishValue |
publishBehavior |
replay |
publishReplay |
return |
of |
selectConcatObserver |
No longer implemented |
selectConcat |
concatMap |
selectMany(fn) |
mergeMap(fn) or flatMap(fn) (alias) |
selectMany(observable) |
mergeMapTo(observable) |
selectManyObserver or flatMapObserver |
No longer implemented |
select |
map |
shareValue |
No longer implemented |
singleInstance |
share |
skipLastWithTime |
No longer implemented |
skipUntilWithTime |
No longer implemented |
slice(start, end) |
skip(start).take(end - start) |
some |
first(fn, () => true, false) |
sum |
reduce((s, v) => s + v, 0) |
switchFirst |
exhaust |
takeLast |
takeLast |
takeLastBufferWithTime |
No longer implemented |
takeLastBuffer |
No longer implemented |
takeLastWithTime |
No longer implemented |
takeUntilWithTime |
No longer implemented |
tapOnCompleted(fn) |
do(null, null, fn) |
tapOnError(fn) |
do(null, fn) |
tapOnNext(fn) |
do(fn) |
tap |
do |
timestamp |
map(v => ({ value: v, timestamp: Date.now() })) |
toMap(keySelector) |
reduce((map, v, i) => map.set(keySelector(v, i), v), new Map()) |
toMap(keySelector, elmentSelector) |
reduce((map, v, i) => map.set(keySelector(v, i), elementSelector(v)), new Map()) |
toSet |
reduce((set, v) => set.add(v)) |
transduce |
No longer implemented |
where |
filter |
windowWithCount |
windowCount |
windowWithTimeOrCount |
No longer implemented |
windowWithTime |
windowTime |
zip |
zip |
To reduce polymorphism and get better performance out of operators, some operators have been split into more than one operator:
RxJS 4 | RxJS 5 | |
---|---|---|
map |
map(project: function, thisArg?: any) |
map(project: function, thisArg?: any) |
map(value: any) |
mapTo(value: any) |
|
flatMap |
flatMap(project: function, resultSelector?: function) |
flatMap(project: function, resultSelector?: function) |
flatMap(value: Observable, resultSelector?: function) |
flatMapTo(value: Observable, resultSelector?: function) |
|
switchMap (aka flatMapLatest ) |
flatMapLatest(project: function, resultSelector?: function) |
switchMap(project: function, resultSelector?: function) |
flatMapLatest(value: Observable, resultSelector?: function) |
switchMapTo(value: Observable, resultSelector?: function) |
|
concatMap |
concatMap(project: function, resultSelector?: function) |
concatMap(project: function, resultSelector?: function) |
concatMap(value: Observable, resultSelector?: function) |
concatMapTo(value: Observable, resultSelector?: function) |
|
buffer |
buffer(closings: Observable) |
buffer(closings: Observable) |
buffer(closingNotifierFactory: function) |
bufferWhen(closingNotifierFactory: function) |
|
buffer(openings: Observable, closingSelector?: function) |
bufferToggle(openings: Observable, closingSelector?: function) |
|
window |
window(closings: Observable) |
window(closings: Observable) |
window(closingNotifierFactory: function) |
windowWhen(closingNotifierFactory: function) |
|
window(openings: Observable, closingSelector?: function) |
windowToggle(openings: Observable, closingSelector?: function) |
|
debounce |
debounce(durationSelector: Observable) |
debounce(durationSelector: Observable) |
debounce(delay: number, scheduler?: Scheduler) |
debounceTime(delay: number, scheduler?: Scheduler) |
|
throttle |
throttle(delay: number, scheduler?: Scheduler) |
throttleTime(delay: number, scheduler?: Scheduler) |
delay |
delay(dueTime: number|Date, scheduler?: Scheduler) |
delay(dueTime: number|Date, scheduler?: Scheduler) |
delay(subscriptionDelay?: Observable, delayDurationSelector: function) |
delayWhen(delayDurationSelector: function, subscriptionDelay?: Observable) |
|
timeout |
timeout(dueTime: number | Date, other?: Error, scheduler?: Scheduler) |
timeout(due: number | Date, errorToSend?: any, scheduler?: Scheduler) |
timeout(dueTime: number | Date, other?: Observable | Promise, scheduler?: Scheduler) |
timeoutWith(due: number | Date, withObservable: ObservableInput, scheduler: Scheduler) |
|
sample |
sample(interval: number, scheduler?: Scheduler) |
sampleTime(interval: number, scheduler?: Scheduler) |
sample(notifier: Observable) |
sample(notifier: Observable) |
RxJS 4 | RxJS 5 | |
---|---|---|
distinctUntilChanged |
distinctUntilChanged(keySelector: function, comparer: function) |
distinctUntilChanged(compare?: (x: K, y: K) => boolean, keySelector?: (x: T) => K): Observable |
RxJS v4 defaulted to a scheduler called Rx.Scheduler.asap
which schedules on the micro task queue. RxJS v5 however defaults to having no scheduler at all; v4 called this Rx.Scheduler.immediate
. This was done to increase performance for the most common use cases.
The names of the Schedulers in RxJS 4 were based off of the Rx.NET implementation. Consequently, some of the names
didn't make sense in a JavaScript context (for example: currentThread
when there's only one thread anyhow).
RxJS 4 | RxJS 5 | |
---|---|---|
Rx.Scheduler.default |
Rx.Scheduler.asap |
schedules on the micro task queue |
Rx.Scheduler.currentThread |
Rx.Scheduler.queue |
schedules on a queue in the current event frame (trampoline scheduler) |
Rx.Scheduler.immediate |
undefined |
by not passing a scheduler to operators that request it, it defaults to recursive execution |
If there is a feature that used to exist in RxJS 4, but no longer does in RxJS 5, please be sure to file an issue (and preferably a PR). In your issue, please describe the use case you have for the operator so we can better understand your need and prioritize it, and/or find and alternative way to compose the desired behavior.