diff --git a/docs_app/content/deprecations/multicasting.md b/docs_app/content/deprecations/multicasting.md index 2d5ee9c900..2e77adc612 100644 --- a/docs_app/content/deprecations/multicasting.md +++ b/docs_app/content/deprecations/multicasting.md @@ -34,7 +34,8 @@ Instead of creating a [ConnectableObservable](/api/index/class/ConnectableObserv ```ts -import { ConnectableObservable, Subject, timer } from 'rxjs'; +import { ConnectableObservable, timer, Subject } from 'rxjs'; + // deprecated const tick$ = new ConnectableObservable( timer(1_000), @@ -44,7 +45,8 @@ tick$.connect(); ```ts -import { connectable, Subject, timer } from 'rxjs'; +import { connectable, timer, Subject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new Subject() @@ -56,7 +58,8 @@ In situations in which the `refCount` method is used, the [share](/api/operators ```ts -import { ConnectableObservable, Subject, timer } from 'rxjs'; +import { ConnectableObservable, timer, Subject } from 'rxjs'; + // deprecated const tick$ = new ConnectableObservable( timer(1_000), @@ -66,8 +69,8 @@ const tick$ = new ConnectableObservable( ```ts -import { Subject, timer } from 'rxjs'; -import { share } from 'rxjs/operators'; +import { timer, share, Subject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( share({ connector: () => new Subject() }) @@ -80,8 +83,8 @@ Where [multicast](/api/operators/multicast) is called with a subject factory, ca ```ts -import { ConnectableObservable, timer, Subject } from 'rxjs'; -import { multicast } from 'rxjs/operators'; +import { timer, multicast, Subject, ConnectableObservable } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( multicast(() => new Subject()) @@ -91,6 +94,7 @@ const tick$ = timer(1_000).pipe( ```ts import { connectable, timer, Subject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new Subject() @@ -101,8 +105,8 @@ Where [multicast](/api/operators/multicast) is called with a subject instance, i ```ts -import { ConnectableObservable, timer, Subject } from 'rxjs'; -import { multicast } from 'rxjs/operators'; +import { timer, multicast, Subject, ConnectableObservable } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( multicast(new Subject()) @@ -112,6 +116,7 @@ const tick$ = timer(1_000).pipe( ```ts import { connectable, timer, Subject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new Subject(), @@ -123,8 +128,8 @@ Where [multicast](/api/operators/multicast) is used in conjunction with [refCoun ```ts -import { timer, Subject } from 'rxjs'; -import { multicast, refCount } from 'rxjs/operators'; +import { timer, multicast, Subject, refCount } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( multicast(() => new Subject()), @@ -134,8 +139,8 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, Subject } from 'rxjs'; -import { share } from 'rxjs/operators'; +import { timer, share, Subject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( share({ connector: () => new Subject() }) @@ -146,8 +151,8 @@ Where [multicast](/api/operators/multicast) is used with a selector, it can be r ```ts -import { timer, combineLatest } from 'rxjs'; -import { multicast } from 'rxjs/operators'; +import { timer, multicast, Subject, combineLatest } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( multicast( @@ -159,8 +164,8 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, combineLatest } from 'rxjs'; -import { connect } from 'rxjs/operators'; +import { timer, connect, combineLatest, Subject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( connect((source) => combineLatest([source, source]), { @@ -175,8 +180,8 @@ If you're using [publish](/api/operators/publish) to create a [ConnectableObserv ```ts -import { ConnectableObservable, timer } from 'rxjs'; -import { publish } from 'rxjs/operators'; +import { timer, publish, ConnectableObservable } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publish() @@ -185,7 +190,8 @@ const tick$ = timer(1_000).pipe( ```ts -import { connectable, timer } from 'rxjs'; +import { connectable, timer, Subject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new Subject(), @@ -197,8 +203,8 @@ And if [refCount](/api/operators/refCount) is being applied to the result of [pu ```ts -import { timer } from 'rxjs'; -import { publish, refCount } from 'rxjs/operators'; +import { timer, publish, refCount } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publish(), @@ -208,14 +214,14 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer } from 'rxjs'; -import { share } from 'rxjs/operators'; +import { timer, share } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( share({ resetOnError: false, resetOnComplete: false, - resetOnRefCountZero: false, + resetOnRefCountZero: false }) ); ``` @@ -224,8 +230,8 @@ If [publish](/api/operators/publish) is being called with a selector, you can us ```ts -import { timer, combineLatest } from 'rxjs'; -import { publish } from 'rxjs/operators'; +import { timer, publish, combineLatest } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publish((source) => combineLatest([source, source])) @@ -234,8 +240,8 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, combineLatest } from 'rxjs'; -import { connect } from 'rxjs/operators'; +import { timer, connect, combineLatest } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( connect((source) => combineLatest([source, source])) @@ -248,8 +254,8 @@ If you're using [publishBehavior](/api/operators/publishBehavior) to create a [C ```ts -import { ConnectableObservable, timer } from 'rxjs'; -import { publishBehavior } from 'rxjs/operators'; +import { timer, publishBehavior, ConnectableObservable } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishBehavior(0) @@ -259,6 +265,7 @@ const tick$ = timer(1_000).pipe( ```ts import { connectable, timer, BehaviorSubject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new BehaviorSubject(0), @@ -270,8 +277,8 @@ And if [refCount](/api/operators/refCount) is being applied to the result of [pu ```ts -import { timer } from 'rxjs'; -import { publishBehavior, refCount } from 'rxjs/operators'; +import { timer, publishBehavior, refCount } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishBehavior(0), @@ -281,15 +288,15 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, BehaviorSubject } from 'rxjs'; -import { share } from 'rxjs/operators'; +import { timer, share, BehaviorSubject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( share({ connector: () => new BehaviorSubject(0), resetOnError: false, resetOnComplete: false, - resetOnRefCountZero: false, + resetOnRefCountZero: false }) ); ``` @@ -300,8 +307,8 @@ If you're using [publishLast](/api/operators/publishLast) to create a [Connectab ```ts -import { ConnectableObservable, timer } from 'rxjs'; -import { publishLast } from 'rxjs/operators'; +import { timer, publishLast, ConnectableObservable } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishLast() @@ -311,6 +318,7 @@ const tick$ = timer(1_000).pipe( ```ts import { connectable, timer, AsyncSubject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new AsyncSubject(), @@ -322,8 +330,8 @@ And if [refCount](/api/operators/refCount) is being applied to the result of [pu ```ts -import { timer } from 'rxjs'; -import { publishLast, refCount } from 'rxjs/operators'; +import { timer, publishLast, refCount } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishLast(), @@ -333,15 +341,15 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, AsyncSubject } from 'rxjs'; -import { share } from 'rxjs/operators'; +import { timer, share, AsyncSubject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( share({ connector: () => new AsyncSubject(), resetOnError: false, resetOnComplete: false, - resetOnRefCountZero: false, + resetOnRefCountZero: false }) ); ``` @@ -352,8 +360,8 @@ If you're using [publishReplay](/api/operators/publishReplay) to create a [Conne ```ts -import { ConnectableObservable, timer } from 'rxjs'; -import { publishReplay } from 'rxjs/operators'; +import { timer, publishReplay, ConnectableObservable } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishReplay(1) @@ -363,6 +371,7 @@ const tick$ = timer(1_000).pipe( ```ts import { connectable, timer, ReplaySubject } from 'rxjs'; + // suggested refactor const tick$ = connectable(timer(1_000), { connector: () => new ReplaySubject(1), @@ -374,8 +383,8 @@ And if [refCount](/api/operators/refCount) is being applied to the result of [pu ```ts -import { timer } from 'rxjs'; -import { publishReplay, refCount } from 'rxjs/operators'; +import { timer, publishReplay, refCount } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishReplay(1), @@ -385,15 +394,15 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, ReplaySubject } from 'rxjs'; -import { share } from 'rxjs/operators'; +import { timer, share, ReplaySubject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, - resetOnRefCountZero: false, + resetOnRefCountZero: false }) ); ``` @@ -402,8 +411,8 @@ If [publishReplay](/api/operators/publishReplay) is being called with a selector ```ts -import { timer, combineLatest } from 'rxjs'; -import { publishReplay } from 'rxjs/operators'; +import { timer, publishReplay, combineLatest } from 'rxjs'; + // deprecated const tick$ = timer(1_000).pipe( publishReplay(1, undefined, (source) => combineLatest([source, source])) @@ -412,8 +421,8 @@ const tick$ = timer(1_000).pipe( ```ts -import { timer, combineLatest, ReplaySubject } from 'rxjs'; -import { connect } from 'rxjs/operators'; +import { timer, connect, combineLatest, ReplaySubject } from 'rxjs'; + // suggested refactor const tick$ = timer(1_000).pipe( connect((source) => combineLatest([source, source]), { diff --git a/docs_app/content/deprecations/resultSelector.md b/docs_app/content/deprecations/resultSelector.md index 4fe676ff79..9f28940bdd 100644 --- a/docs_app/content/deprecations/resultSelector.md +++ b/docs_app/content/deprecations/resultSelector.md @@ -28,24 +28,16 @@ There were two reasons for actually deprecating those parameters: Instead of using the `resultSelector` Argument, you can leverage the [`map`](/api/operators/map) operator on the inner Observable: + ```ts - -import {fromEvent, interval} from 'rxjs'; -import {switchMap, map} from 'rxjs/operators'; +import { fromEvent, switchMap, interval, map } from 'rxjs'; // deprecated fromEvent(document, 'click').pipe( - switchMap(x => interval(0, 1000), (x) => x+1) + switchMap((x) => interval(1000), (_, x) => x + 1) ); // suggested change fromEvent(document, 'click').pipe( - switchMap(x => interval(0, 1000).pipe( - map(x => x+1) - )) + switchMap((x) => interval(1000).pipe(map((x) => x + 1))) ); ``` - - - - - diff --git a/docs_app/content/deprecations/scheduler-argument.md b/docs_app/content/deprecations/scheduler-argument.md index d9d80e6597..5ce868b543 100644 --- a/docs_app/content/deprecations/scheduler-argument.md +++ b/docs_app/content/deprecations/scheduler-argument.md @@ -55,8 +55,7 @@ concat(of('hello '), of('World'), asyncScheduler).subscribe((x) => console.log(x To work around this deprecation you can leverage the [`scheduled`](/api/index/function/scheduled) function. ```ts -import { scheduled, of, asyncScheduler } from 'rxjs'; -import { concatAll } from 'rxjs/operators'; +import { scheduled, of, asyncScheduler, concatAll } from 'rxjs'; scheduled([of('hello '), of('World')], asyncScheduler) .pipe(concatAll()) @@ -78,8 +77,7 @@ combineLatest(of('hello '), of('World'), asyncScheduler).subscribe(console.log); would become: ```ts -import { scheduled, of, asyncScheduler } from 'rxjs'; -import { combineLatestAll } from 'rxjs/operators'; +import { scheduled, of, asyncScheduler, combineLatestAll } from 'rxjs'; scheduled([of('hello '), of('World')], asyncScheduler) .pipe(combineLatestAll()) diff --git a/docs_app/content/deprecations/to-promise.md b/docs_app/content/deprecations/to-promise.md index 40a616b2c4..40fce4a0bc 100644 --- a/docs_app/content/deprecations/to-promise.md +++ b/docs_app/content/deprecations/to-promise.md @@ -31,8 +31,7 @@ the return type change), while the `lastValueFrom` will reject with the {@link E ### Example ```ts -import { interval, lastValueFrom } from 'rxjs'; -import { take } from 'rxjs/operators'; +import { interval, take, lastValueFrom } from 'rxjs'; async function execute() { const source$ = interval(2000).pipe(take(10)); diff --git a/docs_app/content/guide/operators.md b/docs_app/content/guide/operators.md index 01f779bea2..171a7d6168 100644 --- a/docs_app/content/guide/operators.md +++ b/docs_app/content/guide/operators.md @@ -17,8 +17,7 @@ A Pipeable Operator is essentially a pure function which takes one Observable as For example, the operator called [`map`](/api/operators/map) is analogous to the Array method of the same name. Just as `[1, 2, 3].map(x => x * x)` will yield `[1, 4, 9]`, the Observable created like this: ```ts -import { of } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { of, map } from 'rxjs'; of(1, 2, 3) .pipe(map((x) => x * x)) @@ -33,8 +32,7 @@ of(1, 2, 3) will emit `1`, `4`, `9`. Another useful operator is [`first`](/api/operators/first): ```ts -import { of } from 'rxjs'; -import { first } from 'rxjs/operators'; +import { of, first } from 'rxjs'; of(1, 2, 3) .pipe(first()) @@ -270,8 +268,7 @@ If there is a commonly used sequence of operators in your code, use the `pipe()` For example, you could make a function that discarded odd values and doubled even values like this: ```ts -import { pipe } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; +import { pipe, filter, map } from 'rxjs'; function discardOddDoubleEven() { return pipe( diff --git a/docs_app/content/guide/overview.md b/docs_app/content/guide/overview.md index 0f43f2813b..23dc95a2cf 100644 --- a/docs_app/content/guide/overview.md +++ b/docs_app/content/guide/overview.md @@ -46,12 +46,11 @@ document.addEventListener('click', () => console.log(`Clicked ${++count} times`) Using RxJS you isolate the state. ```ts -import { fromEvent } from 'rxjs'; -import { scan } from 'rxjs/operators'; +import { fromEvent, scan } from 'rxjs'; fromEvent(document, 'click') - .pipe(scan(count => count + 1, 0)) - .subscribe(count => console.log(`Clicked ${count} times`)); + .pipe(scan((count) => count + 1, 0)) + .subscribe((count) => console.log(`Clicked ${count} times`)); ``` The **scan** operator works just like **reduce** for arrays. It takes a value which is exposed to a callback. The returned value of the callback will then become the next value exposed the next time the callback runs. @@ -77,15 +76,14 @@ document.addEventListener('click', () => { With RxJS: ```ts -import { fromEvent } from 'rxjs'; -import { throttleTime, scan } from 'rxjs/operators'; +import { fromEvent, throttleTime, scan } from 'rxjs'; fromEvent(document, 'click') .pipe( throttleTime(1000), - scan(count => count + 1, 0) + scan((count) => count + 1, 0) ) - .subscribe(count => console.log(`Clicked ${count} times`)); + .subscribe((count) => console.log(`Clicked ${count} times`)); ``` Other flow control operators are [**filter**](../api/operators/filter), [**delay**](../api/operators/delay), [**debounceTime**](../api/operators/debounceTime), [**take**](../api/operators/take), [**takeUntil**](../api/operators/takeUntil), [**distinct**](../api/operators/distinct), [**distinctUntilChanged**](../api/operators/distinctUntilChanged) etc. @@ -100,7 +98,7 @@ Here's how you can add the current mouse x position for every click, in plain Ja let count = 0; const rate = 1000; let lastClick = Date.now() - rate; -document.addEventListener('click', event => { +document.addEventListener('click', (event) => { if (Date.now() - lastClick >= rate) { count += event.clientX; console.log(count); @@ -112,16 +110,15 @@ document.addEventListener('click', event => { With RxJS: ```ts -import { fromEvent } from 'rxjs'; -import { throttleTime, map, scan } from 'rxjs/operators'; +import { fromEvent, throttleTime, map, scan } from 'rxjs'; fromEvent(document, 'click') .pipe( throttleTime(1000), - map(event => event.clientX), + map((event) => event.clientX), scan((count, clientX) => count + clientX, 0) ) - .subscribe(count => console.log(count)); + .subscribe((count) => console.log(count)); ``` Other value producing operators are [**pluck**](../api/operators/pluck), [**pairwise**](../api/operators/pairwise), [**sample**](../api/operators/sample) etc. diff --git a/docs_app/content/guide/scheduler.md b/docs_app/content/guide/scheduler.md index 3aa88c4e7a..38de9d45d4 100644 --- a/docs_app/content/guide/scheduler.md +++ b/docs_app/content/guide/scheduler.md @@ -10,9 +10,9 @@ In the example below, we take the usual simple Observable that emits values `1`, `2`, `3` synchronously, and use the operator `observeOn` to specify the `async` scheduler to use for delivering those values. + ```ts -import { Observable, asyncScheduler } from 'rxjs'; -import { observeOn } from 'rxjs/operators'; +import { Observable, observeOn, asyncScheduler } from 'rxjs'; const observable = new Observable((observer) => { observer.next(1); @@ -26,14 +26,14 @@ const observable = new Observable((observer) => { console.log('just before subscribe'); observable.subscribe({ next(x) { - console.log('got value ' + x) + console.log('got value ' + x); }, error(err) { console.error('something wrong occurred: ' + err); }, complete() { - console.log('done'); - } + console.log('done'); + }, }); console.log('just after subscribe'); ``` @@ -51,11 +51,11 @@ done Notice how the notifications `got value...` were delivered after `just after subscribe`, which is different to the default behavior we have seen so far. This is because `observeOn(asyncScheduler)` introduces a proxy Observer between `new Observable` and the final Observer. Let's rename some identifiers to make that distinction obvious in the example code: + ```ts -import { Observable, asyncScheduler } from 'rxjs'; -import { observeOn } from 'rxjs/operators'; +import { Observable, observeOn, asyncScheduler } from 'rxjs'; -var observable = new Observable((proxyObserver) => { +const observable = new Observable((proxyObserver) => { proxyObserver.next(1); proxyObserver.next(2); proxyObserver.next(3); @@ -64,16 +64,16 @@ var observable = new Observable((proxyObserver) => { observeOn(asyncScheduler) ); -var finalObserver = { +const finalObserver = { next(x) { - console.log('got value ' + x) + console.log('got value ' + x); }, error(err) { console.error('something wrong occurred: ' + err); }, complete() { - console.log('done'); - } + console.log('done'); + }, }; console.log('just before subscribe'); @@ -83,6 +83,7 @@ console.log('just after subscribe'); The `proxyObserver` is created in `observeOn(asyncScheduler)`, and its `next(val)` function is approximately the following: + ```ts const proxyObserver = { next(val) { @@ -94,31 +95,30 @@ const proxyObserver = { }, // ... -} +}; ``` The `async` Scheduler operates with a `setTimeout` or `setInterval`, even if the given `delay` was zero. As usual, in JavaScript, `setTimeout(fn, 0)` is known to run the function `fn` earliest on the next event loop iteration. This explains why `got value 1` is delivered to the `finalObserver` after `just after subscribe` happened. -The `schedule()` method of a Scheduler takes a `delay` argument, which refers to a quantity of time relative to the Scheduler's own internal clock. A Scheduler's clock need not have any relation to the actual wall-clock time. This is how temporal operators like `delay` operate not on actual time, but on time dictated by the Scheduler's clock. This is specially useful in testing, where a *virtual time Scheduler* may be used to fake wall-clock time while in reality executing scheduled tasks synchronously. +The `schedule()` method of a Scheduler takes a `delay` argument, which refers to a quantity of time relative to the Scheduler's own internal clock. A Scheduler's clock need not have any relation to the actual wall-clock time. This is how temporal operators like `delay` operate not on actual time, but on time dictated by the Scheduler's clock. This is specially useful in testing, where a _virtual time Scheduler_ may be used to fake wall-clock time while in reality executing scheduled tasks synchronously. ## Scheduler Types The `async` Scheduler is one of the built-in schedulers provided by RxJS. Each of these can be created and returned by using static properties of the `Scheduler` object. -| Scheduler | Purpose | -| --- | --- | -| `null` | By not passing any scheduler, notifications are delivered synchronously and recursively. Use this for constant-time operations or tail recursive operations. | -| `queueScheduler` | Schedules on a queue in the current event frame (trampoline scheduler). Use this for iteration operations. | -| `asapScheduler` | Schedules on the micro task queue, which is the same queue used for promises. Basically after the current job, but before the next job. Use this for asynchronous conversions. | -| `asyncScheduler` | Schedules work with `setInterval`. Use this for time-based operations. | -| `animationFrameScheduler` | Schedules task that will happen just before next browser content repaint. Can be used to create smooth browser animations.| - +| Scheduler | Purpose | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `null` | By not passing any scheduler, notifications are delivered synchronously and recursively. Use this for constant-time operations or tail recursive operations. | +| `queueScheduler` | Schedules on a queue in the current event frame (trampoline scheduler). Use this for iteration operations. | +| `asapScheduler` | Schedules on the micro task queue, which is the same queue used for promises. Basically after the current job, but before the next job. Use this for asynchronous conversions. | +| `asyncScheduler` | Schedules work with `setInterval`. Use this for time-based operations. | +| `animationFrameScheduler` | Schedules task that will happen just before next browser content repaint. Can be used to create smooth browser animations. | ## Using Schedulers -You may have already used schedulers in your RxJS code without explicitly stating the type of schedulers to be used. This is because all Observable operators that deal with concurrency have optional schedulers. If you do not provide the scheduler, RxJS will pick a default scheduler by using the principle of least concurrency. This means that the scheduler which introduces the least amount of concurrency that satisfies the needs of the operator is chosen. For example, for operators returning an observable with a finite and small number of messages, RxJS uses no Scheduler, i.e. `null` or `undefined`. For operators returning a potentially large or infinite number of messages, `queue` Scheduler is used. For operators which use timers, `async` is used. +You may have already used schedulers in your RxJS code without explicitly stating the type of schedulers to be used. This is because all Observable operators that deal with concurrency have optional schedulers. If you do not provide the scheduler, RxJS will pick a default scheduler by using the principle of least concurrency. This means that the scheduler which introduces the least amount of concurrency that satisfies the needs of the operator is chosen. For example, for operators returning an observable with a finite and small number of messages, RxJS uses no Scheduler, i.e. `null` or `undefined`. For operators returning a potentially large or infinite number of messages, `queue` Scheduler is used. For operators which use timers, `async` is used. -Because RxJS uses the least concurrency scheduler, you can pick a different scheduler if you want to introduce concurrency for performance purpose. To specify a particular scheduler, you can use those operator methods that take a scheduler, e.g., `from([10, 20, 30], asyncScheduler)`. +Because RxJS uses the least concurrency scheduler, you can pick a different scheduler if you want to introduce concurrency for performance purpose. To specify a particular scheduler, you can use those operator methods that take a scheduler, e.g., `from([10, 20, 30], asyncScheduler)`. **Static creation operators usually take a Scheduler as argument.** For instance, `from(array, scheduler)` lets you specify the Scheduler to use when delivering each notification converted from the `array`. It is usually the last argument to the operator. The following static creation operators take a Scheduler argument: diff --git a/docs_app/content/guide/subject.md b/docs_app/content/guide/subject.md index 5c281f413f..2938b633d9 100644 --- a/docs_app/content/guide/subject.md +++ b/docs_app/content/guide/subject.md @@ -18,10 +18,10 @@ import { Subject } from 'rxjs'; const subject = new Subject(); subject.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); subject.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); subject.next(1); @@ -42,10 +42,10 @@ import { Subject, from } from 'rxjs'; const subject = new Subject(); subject.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); subject.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); const observable = from([1, 2, 3]); @@ -74,8 +74,7 @@ A "multicasted Observable" passes notifications through a Subject which may have Under the hood, this is how the `multicast` operator works: Observers subscribe to an underlying Subject, and the Subject subscribes to the source Observable. The following example is similar to the previous example which used `observable.subscribe(subject)`: ```ts -import { from, Subject } from 'rxjs'; -import { multicast } from 'rxjs/operators'; +import { from, Subject, multicast } from 'rxjs'; const source = from([1, 2, 3]); const subject = new Subject(); @@ -83,10 +82,10 @@ const multicasted = source.pipe(multicast(subject)); // These are, under the hood, `subject.subscribe({...})`: multicasted.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); multicasted.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); // This is, under the hood, `source.subscribe(subject)`: @@ -95,11 +94,11 @@ multicasted.connect(); `multicast` returns an Observable that looks like a normal Observable, but works like a Subject when it comes to subscribing. `multicast` returns a `ConnectableObservable`, which is simply an Observable with the `connect()` method. -The `connect()` method is important to determine exactly when the shared Observable execution will start. Because `connect()` does `source.subscribe(subject)` under the hood, `connect()` returns a Subscription, which you can unsubscribe from in order to cancel the shared Observable execution. +The `connect()` method is important to determine exactly when the shared Observable execution will start. Because `connect()` does `source.subscribe(subject)` under the hood, `connect()` returns a Subscription, which you can unsubscribe from in order to cancel the shared Observable execution. ### Reference counting -Calling `connect()` manually and handling the Subscription is often cumbersome. Usually, we want to *automatically* connect when the first Observer arrives, and automatically cancel the shared execution when the last Observer unsubscribes. +Calling `connect()` manually and handling the Subscription is often cumbersome. Usually, we want to _automatically_ connect when the first Observer arrives, and automatically cancel the shared execution when the last Observer unsubscribes. Consider the following example where subscriptions occur as outlined by this list: @@ -108,17 +107,16 @@ Consider the following example where subscriptions occur as outlined by this lis 3. The `next` value `0` is delivered to the first Observer 4. Second Observer subscribes to the multicasted Observable 5. The `next` value `1` is delivered to the first Observer -5. The `next` value `1` is delivered to the second Observer -1. First Observer unsubscribes from the multicasted Observable -5. The `next` value `2` is delivered to the second Observer -1. Second Observer unsubscribes from the multicasted Observable -1. **The connection to the multicasted Observable is unsubscribed** +6. The `next` value `1` is delivered to the second Observer +7. First Observer unsubscribes from the multicasted Observable +8. The `next` value `2` is delivered to the second Observer +9. Second Observer unsubscribes from the multicasted Observable +10. **The connection to the multicasted Observable is unsubscribed** To achieve that with explicit calls to `connect()`, we write the following code: ```ts -import { interval, Subject } from 'rxjs'; -import { multicast } from 'rxjs/operators'; +import { interval, Subject, multicast } from 'rxjs'; const source = interval(500); const subject = new Subject(); @@ -126,7 +124,7 @@ const multicasted = source.pipe(multicast(subject)); let subscription1, subscription2, subscriptionConnect; subscription1 = multicasted.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); // We should call `connect()` here, because the first // subscriber to `multicasted` is interested in consuming values @@ -134,7 +132,7 @@ subscriptionConnect = multicasted.connect(); setTimeout(() => { subscription2 = multicasted.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); }, 600); @@ -157,8 +155,7 @@ If we wish to avoid explicit calls to `connect()`, we can use ConnectableObserva Below is an example: ```ts -import { interval, Subject } from 'rxjs'; -import { multicast, refCount } from 'rxjs/operators'; +import { interval, Subject, multicast, refCount } from 'rxjs'; const source = interval(500); const subject = new Subject(); @@ -169,13 +166,13 @@ let subscription1, subscription2; // it is the first subscriber to `refCounted` console.log('observerA subscribed'); subscription1 = refCounted.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); setTimeout(() => { console.log('observerB subscribed'); subscription2 = refCounted.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); }, 600); @@ -217,14 +214,14 @@ import { BehaviorSubject } from 'rxjs'; const subject = new BehaviorSubject(0); // 0 is the initial value subject.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); subject.next(1); subject.next(2); subject.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); subject.next(3); @@ -240,7 +237,7 @@ subject.next(3); ## ReplaySubject -A `ReplaySubject` is similar to a `BehaviorSubject` in that it can send old values to new subscribers, but it can also *record* a part of the Observable execution. +A `ReplaySubject` is similar to a `BehaviorSubject` in that it can send old values to new subscribers, but it can also _record_ a part of the Observable execution. A `ReplaySubject` records multiple values from the Observable execution and replays them to new subscribers. @@ -251,7 +248,7 @@ import { ReplaySubject } from 'rxjs'; const subject = new ReplaySubject(3); // buffer 3 values for new subscribers subject.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); subject.next(1); @@ -260,7 +257,7 @@ subject.next(3); subject.next(4); subject.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); subject.next(5); @@ -277,15 +274,16 @@ subject.next(5); // observerB: 5 ``` -You can also specify a *window time* in milliseconds, besides of the buffer size, to determine how old the recorded values can be. In the following example we use a large buffer size of `100`, but a window time parameter of just `500` milliseconds. +You can also specify a _window time_ in milliseconds, besides of the buffer size, to determine how old the recorded values can be. In the following example we use a large buffer size of `100`, but a window time parameter of just `500` milliseconds. + ```ts import { ReplaySubject } from 'rxjs'; const subject = new ReplaySubject(100, 500 /* windowTime */); subject.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); let i = 1; @@ -293,7 +291,7 @@ setInterval(() => subject.next(i++), 200); setTimeout(() => { subject.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); }, 1000); @@ -320,7 +318,7 @@ import { AsyncSubject } from 'rxjs'; const subject = new AsyncSubject(); subject.subscribe({ - next: (v) => console.log(`observerA: ${v}`) + next: (v) => console.log(`observerA: ${v}`), }); subject.next(1); @@ -329,7 +327,7 @@ subject.next(3); subject.next(4); subject.subscribe({ - next: (v) => console.log(`observerB: ${v}`) + next: (v) => console.log(`observerB: ${v}`), }); subject.next(5); @@ -342,7 +340,6 @@ subject.complete(); The AsyncSubject is similar to the [`last()`](/api/operators/last) operator, in that it waits for the `complete` notification in order to deliver a single value. - ## Void subject Sometimes the emitted value doesn't matter as much as the fact that a value was emitted. @@ -371,10 +368,10 @@ import { Subject } from 'rxjs'; const subject = new Subject(); // Shorthand for Subject subject.subscribe({ - next: () => console.log('One second has passed') + next: () => console.log('One second has passed'), }); setTimeout(() => subject.next(), 1000); ``` -Before version 7, the default type of Subject values was `any`. `Subject` disables type checking of the emitted values, whereas `Subject` prevents accidental access to the emitted value. If you want the old behavior, then replace `Subject` with `Subject`. \ No newline at end of file +Before version 7, the default type of Subject values was `any`. `Subject` disables type checking of the emitted values, whereas `Subject` prevents accidental access to the emitted value. If you want the old behavior, then replace `Subject` with `Subject`. diff --git a/docs_app/content/guide/testing/marble-testing.md b/docs_app/content/guide/testing/marble-testing.md index 303f20330b..51e79878b3 100644 --- a/docs_app/content/guide/testing/marble-testing.md +++ b/docs_app/content/guide/testing/marble-testing.md @@ -10,7 +10,7 @@ We can test our _asynchronous_ RxJS code _synchronously_ and deterministically b ```ts import { TestScheduler } from 'rxjs/testing'; -import { throttleTime } from 'rxjs/operators'; +import { throttleTime } from 'rxjs'; const testScheduler = new TestScheduler((actual, expected) => { // asserting the two objects are equal - required