RxJs Basics Flashcards

1
Q

What is an observable?

A

A lazily evaluated computation that may produce zero to possibly infinite values.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

When creating an observable with new or Observable.create, what argument do you provide?

A

A subscriber argument which is a function that is evaluated when the observable is first subscribed to. You can call next, error, or complete in this function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What callbacks can observers register when subscribing to an observable?

A

next, for handling new values
error, for handling errors
complete, for handling completion of the observable

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What values are emitted by the following observable?

const observable = new Observable((subscriber) => {
  subscriber.next("one");
  subscriber.next("two");
  subscriber.complete();
  subscriber.next("three");
  subscriber.next("four");
});
A

“one” and “two”, nothing emits after the call to complete.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What alternative do you have to supplying the subscription object with next, error, and complete functions?

A

Pass the callbacks as parameters to overloads of the subscribe function, e.g.

observable.subscribe(
  value => console.log(value),
  null, // null for error callback
  () => console.log('completed')
)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Do observables always deliver values asynchronously?

A

No, they can deliver values synchronously or asynchronously.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

When you return a function from the subscriber argument passed to the Observable constructor, what is it used for?

A

It is run to clean up resources (e.g. timers) when the observable completes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What is returned when you call subscribe on an observable, and what might you use it for?

A

A subscription object which has: anunsubscribe method on it that allows the consumer to declare they are done with the observable (as opposed to the producer explicitly calling complete), and a add method which allows you to join observables together.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Is the complete callback called when you call unsubscribe on a subscription?

A

No, the complete callback is only called when the producer, i.e. the observable, explicitly calls complete.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

How can you join multiple subscriptions together so that you can unsubscribe them all at the same time?

A

By calling add on the subscription object, e.g. subscriptionOne.add(subscriptionTwo)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What is a creation operator?

A

An operator that lifts a non-observable value or source into an observable, e.g. of(‘my value’)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How would you import the fromEvent creation operator?

A

import { fromEvent } from ‘rxjs’

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

How would you create and subscribe to and observable that emits whenever the user clicks anywhere in the document?

A

import { fromEvent } from ‘rxjs’

const source$ = fromEvent(document, 'click')
const sub = source$.subscribe(next => ....)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How would you use the of creation operator to create an observable that will emit “foo”, “bar”, “baz”, in sequence?

A

import { of } from ‘rxjs’

const source$ = of(“foo”, “bar”, “baz”)
source$.subscribe(next => …)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What other creation operator could you use in place of of(1,2,3,4,5)?

A

range(1, 5)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

What would the output be when the following code is run?

import { of } from 'rxjs'
const source$ = of("foo", "bar", "baz")
source$.subscribe(console.log)
console.log("zap")
A

“foo”
“bar”
“baz”
“zap”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What is the difference between of([1,2,3]) and from([1,2,3])?

A

of will emit a single array value, [1,2,3]

from will emit the elements of the array one by one

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What does the following code do?

function* hello() {
    yield 'Hello';
    yield 'World';
};

const x = hello();
from(x).subscribe(console.log);
A

Creates an iterator by calling the generator function hello. Iterators have a next method on them that returns the yielded values. The rxjs from creation operator can use this iterator to create a stream.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Can the from creation operator take a Promise?

A

Yes

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

What does the interval creation operator do?

A

Emits a incrementing sequence of numbers, starting at zero, at the interval you specify. e.g. interval(1000) emits a number every second.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

What does timer(2000) do?

A

Emits 0 after 2 seconds, then completes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

What does timer(5000, 500) do?

A

Emits 0 after 5 seconds, then emits numbers in sequence, starting at 1, every half second.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

What is a ‘pipeable’ operator?

A

A function that takes an observable as an input, and returns another observable as an output.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

How would you apply the map operator to a observable created by of(1,2,3), without using the pipe method?

A

map(value => …)(of(1, 2, 3))

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

Do rxjs pipeable operators modify the input observable?

A

No, they return a new observable, without altering the input/source observable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

What is a marble diagram?

A

A visualization of a source input, passed to a pipeable operator (or composition of operators), and the resulting output, e.g.

input$: –1—-2—-3
map(value => value * 2)
output$: –2—-4—-6

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

What does a solid vertical line on the output line of a marble diagram represent?

A

The completion of the observable

28
Q

What does an X on the output line of a marble diagram represent?

A

An error.

29
Q

Where are pipeable operators imported from?

A

‘rxjs/operators’

30
Q

What does the map operator do?

A

Applies a given projection function to each value emitted by the source observable.

31
Q

What does the pluck operator do?

A

Maps each source value to it’s specified nested property.

32
Q

What does the mapTo operator do?

A

Emits the given constant value on the output Observable every time the source Observable emits a value.

33
Q

What does the filter operator do?

A

Filters out values emitted by an input source that do not pass the supplied predicate function.

34
Q

What does the reduce operator do?

A

Accumulates emitted values in a single ‘accumulator’ value, which gets emitted when the source observable completes.

35
Q

What is output when the following code is run?

interval(1000)
  .pipe(
    reduce((acc, next) => acc + next, 0)
  )
  .subscribe({
    complete: () => console.log('Complete!')
  });
A

Nothing! The reduce operator is accumulating, but it will only emit once the source observable completes. Since interval never completes, the reduce never emits.

36
Q

What is the difference between the scan and reduce operators?

A

scan emits a value every time the source observable emits value and reduce only emits a value when the source observable completes.

37
Q

What happens when you return a value from the tap operator?

A

Nothing. The return value is ignored.

38
Q

How would you use the tap operator to console log when an observable completes?

A

observable$.pipe(
tap({ complete: () => console.log(‘completed’) }
)

39
Q

How could you make the x$ observable complete after it receives three values from the numbers$ source?

const numbers$ = of(1,2,3,4,5)
const x$ = numbers$.pipe(???).subscribe(console.log)
A

Use the take pipeline operator, e.g.

const numbers$ = of(1,2,3,4,5)
const x$ = numbers$.pipe(take(3)).subscribe(console.log)
40
Q

Without using filter or take, how could you make the x$ observable emit only the number 2, then complete?

const numbers$ = of(1,2,3,4,5)
const x$ = numbers$.pipe(???).subscribe(console.log)
A

Use the first operator, e.g.

const numbers$ = of(1,2,3,4,5)
const x$ = numbers$.pipe(
first(y => y === 2)
).subscribe(console.log)
41
Q

When would you use the takeWhile operator?

A

When you want to limit the life of your observable, based on a predefined condition.

42
Q

Explain what the takeUntil pipeline operator does?

takeUntil(notifier: ObservableInput)

A

It consumes values emitted by its source observable until another observable, commonly called the notifier observable, emits a value.

43
Q

What will the following code output? Why?

const numbers$ = of(1, '1', 2, 3, 3, 3, 4, 5, 3);
numbers$.pipe(distinctUntilChanged()).subscribe(console.log);
A

output:
1, 1, 2, 3, 4, 5, 3

distinctUntilChanged emits unique values based on a === comparison to the last emitted value. So the string ‘1’ is different to the number 1, and the 3 and the end is emitted because the previous emission was not a 3.

44
Q

What does the debounceTime operator do?

A

Only emits values from it’s source observable when the provided number of ms has elapsed between emissions.

45
Q

Explain the following signature:

throttleTime(duration: number, scheduler: SchedulerLike = asyncScheduler, config: ThrottleConfig = defaultThrottleConfig)
A

Emits a value from the source Observable, then ignores subsequent source values for duration milliseconds, then repeats this process. The final config argument can be used to configure when in the throttle window values are emitted.

46
Q

How do the debounceTime and sampleTime rate limiting operators differ?

A

debounceTime emits a notification from the source Observable only after a particular time span has passed without another source emission.

whereas sampleTime emits the most recently emitted value from the source within periodic time intervals.

47
Q

What does the auditTime operator do?

A

Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.

48
Q

What is a ‘flattening’ operator?

A

Operators that convert a higher order observable into a first-order ordinary observable (by ‘flattening’).

49
Q

What does the mergeAll operator do?

A

Converts a higher-order Observable into a first-order Observable which concurrently delivers all values that are emitted on the inner Observables (order not guaranteed).

50
Q

What does the mergeMap operator do?

A

Maps each value to an Observable, then flattens all of these inner Observables using mergeAll.

51
Q

How does the switchMap operator differ from the mergeAll operator?

A

The switchMap operator cancels previous inner observables when the source observable emits again, whereas the mergeAll operator emits values from multiple inner observables concurrently, leaving clean up to the programmer.

52
Q

When using Observables to request data from a server via a GET request, which you then use to update the UI, would you use mergeAll or switchMap operator? Why?

A

switchMap because you want to cancel previous requests as new source values are emitted (e.g. a type-ahead with server side lookup scenario).

53
Q

What does the concatMap operator do?

A

Maintains one active inner subscription by queuing inner Observables in a FIFO fashion. The next observable is activated once the previous completes.

54
Q

When would you use the concatMap operator?

A

When the order of execution is important and inner Observables have finite lifespans.

55
Q

What does the exhaustMap operator do?

A

Ignores values emitted from the source when there is an active inner Observable. The inner Observable must complete before new source emissions are handled.

56
Q

What does the catchError operator do?

A

Catches errors thrown by its source Observable. It can then either throw and error, or return an Observable to keep the Observable going.

57
Q

What does the following code output?

of(1,2,3).pipe(
  startWith('a', 'b', 'c'),
  endWith('d', 'e', 'f')
).subscribe(console.log);
A
a
b
c
1
2
3
d
e
f
58
Q

What does the concat creation operator do?

A

It queues multiple Observables to run to completion, one after the other.

59
Q

Which of the following are creation operators and which are pipeable operators?

map
concat
merge
concatMap

A

map pipeable
concat creation
merge creation
concatMap pipeable

60
Q

What does the empty operator do?

A

Creates an observable that emits no values, then completes.

61
Q

What does the following code do?

merge(
  startClick$.pipe(mapTo(true)), 
  pauseClick$.pipe(mapTo(false))
)
A

Creates an output Observable which concurrently emits all values from every given input Observable.

62
Q

What does the combineLatest operator do?

A

Joins multiple Observables into a single Observable that emits the most recent values from every input Observable, whenever any input Observable emits. All input Observables must emit once before any combination can be emitted.

63
Q

What is the difference between the combineLatest and withLatestFrom operators, and when would you use each?

A

combineLatest is a creation operator that takes multiple Observables and creates a single observable that emits the latest value seen from all the input streams, e.g.

combineLatest(keyup$, click$)

withLatestFrom is a pipeable operator that combines another Observable with its single source Observable, e.g.

click$.pipe(withLatestFrom(interval(1000)))

64
Q

What combination operator would you use to consume the last value before completion, across multiple Observables?

A

forkJoin

65
Q

What does the following code do:

forkJoin({
  user: ajax.getJSON(`${GITHUB_API_BASE}/users/reactivex`),
  repo: ajax.getJSON(`${GITHUB_API_BASE}/users/reactivex/repos`)
}).subscribe(console.log);
A

Creates a single Observable, by combining two ajax Observables. The returned Observable emits objects with the keys provided (user and repo) once both of the ajax Observables complete.