乐闻世界logo
搜索文章和话题

What are the differences between RxJS 6 and RxJS 7?

2月21日 16:54

Major Changes Between RxJS 6 and RxJS 7

1. Import Changes

RxJS 6:

javascript
// Creation operators import { of, from, interval } from 'rxjs'; // Operators (using pipe) import { map, filter, switchMap } from 'rxjs/operators'; // Utility functions import { Subscription } from 'rxjs';

RxJS 7:

javascript
// Import method is basically the same, but more modular import { of, from, interval } from 'rxjs'; import { map, filter, switchMap } from 'rxjs/operators'; // Added some new operators import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

2. New Operators

RxJS 7 added several useful operators:

1. partition

Splits an Observable into two based on a predicate function.

javascript
import { of, partition } from 'rxjs'; const source$ = of(1, 2, 3, 4, 5, 6); const [evens$, odds$] = partition(source$, x => x % 2 === 0); evens$.subscribe(x => console.log('Even:', x)); // 2, 4, 6 odds$.subscribe(x => console.log('Odd:', x)); // 1, 3, 5

2. Improved tap

tap now accepts an object to handle different notification types separately.

javascript
import { of } from 'rxjs'; import { tap } from 'rxjs/operators'; of(1, 2, 3).pipe( tap({ subscribe: () => console.log('Subscribed'), next: value => console.log('Next:', value), error: error => console.log('Error:', error), complete: () => console.log('Completed'), unsubscribe: () => console.log('Unsubscribed') }) ).subscribe();

3. connectable Operator

Simplifies the creation of multicast Observables.

javascript
import { interval, connectable } from 'rxjs'; import { take } from 'rxjs/operators'; const source$ = interval(1000).pipe(take(5)); const connectable$ = connectable(source$); connectable$.subscribe(value => console.log('Subscriber 1:', value)); connectable$.subscribe(value => console.log('Subscriber 2:', value)); connectable$.connect();

4. Improved shareReplay

shareReplay now supports configuration objects.

javascript
import { interval } from 'rxjs'; import { shareReplay, take } from 'rxjs/operators'; const shared$ = interval(1000).pipe( take(5), shareReplay({ bufferSize: 2, refCount: true }) );

5. Improved Type Inference for filter

Better TypeScript type inference.

javascript
import { of } from 'rxjs'; import { filter } from 'rxjs/operators'; const source$ = of(1, 2, 3, 4, 5); // In RxJS 7, type inference is more accurate const even$ = source$.pipe( filter(x => x % 2 === 0) // x is inferred as number ); even$.subscribe(x => console.log(x)); // x is of type number

3. Deprecated Operators

The following operators are deprecated in RxJS 7:

1. throwError

RxJS 6:

javascript
import { throwError } from 'rxjs'; throwError('Error message');

RxJS 7:

javascript
import { throwError } from 'rxjs'; // Recommended to use factory function throwError(() => new Error('Error message'));

2. Static Methods concat and merge

Still available, but concatWith and mergeWith are recommended.

javascript
import { of, concat, merge } from 'rxjs'; // Still available concat(of(1), of(2)).subscribe(); merge(of(1), of(2)).subscribe(); // Recommended of(1).pipe(concatWith(of(2))).subscribe(); of(1).pipe(mergeWith(of(2))).subscribe();

4. Performance Optimizations

1. Smaller Bundle Size

RxJS 7 reduces bundle size through tree-shaking optimization.

javascript
// RxJS 7 only imports needed operators import { of } from 'rxjs'; import { map } from 'rxjs/operators'; // Only of and map will be included in the bundle

2. Faster Execution Speed

Execution speed of some operators has been optimized.

javascript
import { of } from 'rxjs'; import { map, filter } from 'rxjs/operators'; // These operators execute faster in RxJS 7 of(1, 2, 3, 4, 5).pipe( map(x => x * 2), filter(x => x > 5) ).subscribe();

5. TypeScript Improvements

1. Better Type Inference

javascript
import { of } from 'rxjs'; import { map, filter } from 'rxjs/operators'; // In RxJS 7, type inference is more accurate const result$ = of(1, 2, 3).pipe( map(x => x.toString()), // Inferred as Observable<string> filter(x => x.length > 0) );

2. Strict Type Checking

javascript
import { of } from 'rxjs'; import { map } from 'rxjs/operators'; // In RxJS 7, type checking is stricter of(1, 2, 3).pipe( map(x => x.toUpperCase()) // TypeScript error: number doesn't have toUpperCase );

6. Error Handling Improvements

1. Better Error Messages

javascript
import { of } from 'rxjs'; import { map } from 'rxjs/operators'; of(1, 2, 3).pipe( map(x => { if (x === 2) throw new Error('Custom error'); return x; }) ).subscribe({ error: error => { console.log(error.message); // Clearer error message } });

2. Improved onErrorResumeNext

javascript
import { of, onErrorResumeNext } from 'rxjs'; const source1$ = of(1, 2, 3).pipe( map(x => { if (x === 2) throw new Error('Error'); return x; }) ); const source2$ = of(4, 5, 6); onErrorResumeNext(source1$, source2$).subscribe(console.log); // Output: 1, 4, 5, 6

7. Scheduler Improvements

1. Improved animationFrameScheduler

javascript
import { interval, animationFrameScheduler } from 'rxjs'; import { take } from 'rxjs/operators'; // In RxJS 7, animationFrameScheduler is more stable interval(0, animationFrameScheduler).pipe( take(60) ).subscribe(frame => { console.log('Frame:', frame); });

2. Improved asapScheduler

javascript
import { of, asapScheduler } from 'rxjs'; // In RxJS 7, asapScheduler has better performance of(1, 2, 3, asapScheduler).subscribe(value => { console.log(value); });

8. Testing Tool Improvements

1. Improved TestScheduler

javascript
import { TestScheduler } from 'rxjs/testing'; // In RxJS 7, TestScheduler is easier to use const testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); testScheduler.run(({ cold, expectObservable }) => { const source$ = cold('-a-b-c|'); const expected = '-a-b-c|'; expectObservable(source$).toBe(expected); });

2. Improved marble testing

javascript
import { TestScheduler } from 'rxjs/testing'; // In RxJS 7, marble testing is more intuitive testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => { const source$ = cold('-a-b-c|'); const expected = '-a-b-c|'; expectObservable(source$).toBe(expected); });

9. Documentation and Example Improvements

1. Better Documentation

RxJS 7 provides more detailed documentation and examples.

javascript
// Official documentation provides more practical examples import { of } from 'rxjs'; import { map, filter } from 'rxjs/operators'; of(1, 2, 3, 4, 5).pipe( map(x => x * 2), filter(x => x > 5) ).subscribe(console.log);

2. More Best Practices

Official documentation includes more best practice recommendations.

javascript
// Recommended to use pipe instead of chaining import { of } from 'rxjs'; import { map, filter } from 'rxjs/operators'; // ✅ Recommended of(1, 2, 3).pipe( map(x => x * 2), filter(x => x > 5) ).subscribe(); // ❌ Not recommended of(1, 2, 3).pipe( map(x => x * 2) ).pipe( filter(x => x > 5) ).subscribe();

10. Migration Guide

1. Migrating from RxJS 6 to RxJS 7

bash
# Upgrade RxJS npm install rxjs@7 # Check for deprecated APIs npm run lint

2. Common Migration Issues

Issue 1: Usage of throwError

javascript
// ❌ RxJS 6 throwError('Error message'); // ✅ RxJS 7 throwError(() => new Error('Error message'));

Issue 2: Type inference issues

javascript
// May need explicit types import { of } from 'rxjs'; import { map } from 'rxjs/operators'; const result$ = of(1, 2, 3).pipe( map(x => x.toString()) ) as Observable<string>;

Summary

Major improvements of RxJS 7 compared to RxJS 6:

  1. New Operators: partition, connectable, etc.
  2. Performance Optimization: Smaller bundle size, faster execution speed
  3. TypeScript Improvements: Better type inference and strict type checking
  4. Error Handling: Better error messages and handling mechanisms
  5. Scheduler Improvements: More stable and efficient schedulers
  6. Testing Tools: Easier to use TestScheduler
  7. Documentation Improvements: More detailed documentation and examples

Migrating to RxJS 7 can bring better performance and development experience, but be aware of some API changes.

标签:Rxjs