RxJS Top Ten - Code This, Not That

Fireship
25 Mar 201914:43

Summary

TLDRThis video script offers an insightful introduction to RxJS, a JavaScript library for managing asynchronous streams of data. It explains the importance of RxJS in handling data over time, such as DOM events and WebSockets, and how it overcomes 'callback hell'. The tutorial covers the installation, basic concepts like observables, subjects, and operators, and demonstrates practical examples. It also addresses common issues like memory leaks and strategies to prevent them, making it an informative guide for developers looking to harness the power of reactive programming.

Takeaways

  • 🎵 RxJS is a challenging but rewarding JavaScript library for managing data flow over time.
  • 📈 RxJS is popular because it handles asynchronous data streams more efficiently than JavaScript alone.
  • 🔄 The core concept in RxJS is the 'Observable,' which acts as a data wrapper that can be subscribed to.
  • 🚰 Think of using RxJS like plumbing, with Observables as pipes for data.
  • 🌳 RxJS is tree-shakable, meaning you should only import the classes and operators you need to minimize bundle size.
  • 🔔 An Observable notifies subscribers whenever data changes, making it a key part of reactive programming.
  • 🔄 Subjects in RxJS are hot Observables that allow new values to be pushed to them, like a pump.
  • 🌟 Behavior Subjects store the last emitted value, ensuring all subscribers receive the latest data.
  • ⚙️ Operators in RxJS help manipulate data flow; examples include 'map,' 'filter,' 'scan,' 'tap,' 'debounce,' and 'throttle.'
  • 🛠️ RxJS offers tools for error handling (e.g., 'catchError') and memory leak prevention (e.g., 'takeWhile,' 'takeUntil').

Q & A

  • What is RxJS and why is it considered difficult but rewarding to learn?

    -RxJS is a JavaScript library for reactive programming using Observables to handle asynchronous streams of data. It's considered difficult due to its complex concepts and functional programming approach, but rewarding because it provides powerful tools for controlling data flow over time.

  • How does RxJS compare in popularity to Angular and other libraries?

    -RxJS is quite popular, with more daily npm downloads than Angular. It is one of the largest functional libraries, second only to lodash, indicating its widespread use in handling asynchronous data streams.

  • Why do we need RxJS when we already have Promises in JavaScript?

    -While Promises are useful for handling single asynchronous values, RxJS is needed for dealing with real-time streams of data. Promises do not support multiple values over time, which is where RxJS, with its Observables, comes into play.

  • What is the fundamental class in RxJS and how is it used?

    -The fundamental class in RxJS is the Observable. It acts as a wrapper for data that can be subscribed to, notifying subscribers of new data changes over time.

  • How can one prevent bundling the entire RxJS library in their project?

    -To prevent bundling the entire library, one should import only the specific classes and operators needed in their source code. This practice, known as tree shaking, significantly reduces the final bundle size.

  • What is the difference between the 'of' and 'from' functions in RxJS?

    -The 'of' function creates an Observable from a set of arguments and emits each of them as individual items. The 'from' function takes an array, promise, or iterable and emits each individual item from the source.

  • How can RxJS be used to handle DOM events?

    -RxJS can create an Observable from DOM events using the 'fromEvent' function. By passing a DOM element and the event type, an Observable can be set up to emit events each time the specified event occurs on the element.

  • What are the differences between hot and cold observables in RxJS?

    -Hot observables can have multiple subscriptions and can emit items regardless of the number of subscribers. Cold observables, on the other hand, create a new execution for each subscription and do not emit items until a subscription is made.

  • What is a Subject in RxJS and how does it differ from an Observable?

    -A Subject in RxJS is a special type of Observable that allows values to be multicasted to many Observers. Additionally, it has an added 'next' method to push new values into the stream after it has been created, unlike a regular Observable.

  • What are some common operators used in RxJS to control the flow of data?

    -Some common operators in RxJS include 'map' for transforming emitted values, 'filter' to emit only certain values, 'take' to emit only a specific number of values, and 'catchError' to handle errors within the Observable stream.

  • How can one prevent memory leaks when using RxJS subscriptions?

    -Memory leaks can be prevented by unsubscribing from subscriptions when they are no longer needed. Alternatively, using operators like 'takeWhile' can automatically stop the subscription when a certain condition is met, thus avoiding the need for manual unsubscription.

  • What is the purpose of the 'switchMap' operator in RxJS?

    -The 'switchMap' operator is used to switch from an outer Observable to an inner Observable based on the emitted values of the outer Observable. It is particularly useful for handling relational data or when you need to switch context based on the data flow.

  • What are 'combineLatest' and 'merge' operators in RxJS and how do they differ?

    -The 'combineLatest' operator takes an array of Observables and emits an array containing the latest values from each Observable whenever any of them emit a new value. The 'merge' operator, on the other hand, subscribes to each Observable in the array and simply emits all values from them as they come in, without waiting for the others.

Outlines

00:00

🌐 Introduction to RxJS

This paragraph introduces RxJS as a challenging yet rewarding JavaScript library that manages data flow over time. It highlights the library's popularity, surpassing daily npm downloads of Angular, and emphasizes its utility in handling asynchronous streams of data, such as those from Firebase, DOM events, WebSockets, and file uploads. The speaker explains that JavaScript lacks native tools for dealing with such streams, leading to the use of RxJS. The fundamental concept of an Observable is introduced, described as a data wrapper that can be subscribed to, with changes in data notifying subscribers. The speaker also discusses the importance of importing only necessary RxJS classes and operators to minimize bundle size, and demonstrates creating a basic Observable and Subscription.

05:00

🔌 Creating Observables and Understanding Hot vs. Cold Observables

The speaker delves into creating observables from scratch, explaining the process of emitting data to subscribers. They discuss the concept of observables being completed, which stops further data emission. Various methods for creating observables are introduced, such as 'of' for raw values, 'from' for arrays, promises, or iterables, and 'fromEvent' for DOM events. The difference between 'of' and 'from' is clarified, with examples. The paragraph also touches on the creation of observables from time intervals. The concept of schedulers is briefly mentioned, allowing control over the timing of observable emissions. The distinction between hot and cold observables is explored, with examples demonstrating how cold observables generate values upon subscription, while hot observables can have multiple subscriptions. The use of 'share' and 'replay' operators to make cold observables hot is discussed, along with the introduction of Subjects and BehaviorSubjects, which allow for new values to be pushed to the stream after creation.

10:02

🛠 RxJS Operators for Data Flow Control

This section focuses on RxJS operators that control the flow of data through observables. The speaker demonstrates the use of the 'map' operator to transform emitted values and the 'scan' operator for accumulating values. The importance of the order of operators in a pipe is stressed, as it affects the outcome. The 'filter' operator is introduced to selectively emit values based on a condition. The 'take' operator is used to limit the number of emitted values, and the 'tap' operator is shown for triggering side effects within the observable pipe. The concept of back pressure, where an observable emits more values than needed, is addressed, with solutions like 'debounce', 'throttle', and 'buffer' operators provided to manage the flow. The speaker also introduces 'switchMap' for switching between observables based on data, and discusses combining observables using 'combineLatest' and 'merge'. Error handling in observables is touched upon with the 'catchError' operator, and strategies for preventing memory leaks, such as unsubscribing and using 'takeWhile', are discussed.

Mindmap

Keywords

💡RxJS

RxJS, short for Reactive Extensions for JavaScript, is a library for reactive programming using Observables, facilitating the composition of asynchronous and event-based programs. It's central to the video's theme, as it's the main subject being discussed. The script introduces RxJS as a tool for controlling data flow over time, with examples of its use throughout the video.

💡Observable

An Observable is a core concept in RxJS, representing a stream of data that can emit values over time. It's defined in the script as a 'wrapper for some data that can be subscribed to', and it's the fundamental building block for creating reactive applications. The video demonstrates creating an Observable from scratch and subscribing to it to react to emitted data.

💡Subscription

A Subscription in RxJS is the mechanism by which code reacts to values emitted by an Observable. It's explained in the script as 'reacting to changes in the observable data'. The video shows creating a subscription by calling the 'subscribe' method on an Observable, which takes a function that is executed each time the Observable emits a new value.

💡Operators

Operators in RxJS are functions that enable the manipulation of Observables in various ways, such as transforming the data, filtering, or combining multiple Observables. The script mentions several operators like 'map', 'filter', 'scan', and 'take', illustrating how they can be used to control the flow of data within an Observable stream.

💡Subjects

Subjects in RxJS are a type of Observable that can multicast to many Observers. They are described in the script as 'hot observables' that can have multiple subscriptions and can push new values to the stream after creation. The video contrasts Subjects with other Observables and demonstrates their unique ability to emit new values to subscribers.

💡BehaviorSubject

A BehaviorSubject is a variant of Subject that holds a value and emits it to new subscribers immediately upon subscription. It's highlighted in the script as having 'the concept of a current value', which makes it particularly useful for state management in applications. The video illustrates how BehaviorSubject ensures that all subscribers receive the last emitted value.

💡Schedulers

Schedulers in RxJS are used to control the execution context of work within an Observable sequence. The script touches on this concept, mentioning that RxJS can be synchronous or asynchronous and that schedulers can be modified to control the timing of when values are emitted from an Observable.

💡Hot and Cold Observables

Hot Observables can have multiple subscribers and emit values independently of the number of subscribers, while Cold Observables create a new execution for each subscription. The video script uses the terms 'hot' and 'cold' to explain the difference in how Observables share data with multiple subscribers, with examples of making a Cold Observable 'hot' using operators like 'share' and 'shareReplay'.

💡Reactive Programming

Reactive Programming is a programming paradigm that deals with data streams and the propagation of change. The script introduces the concept by stating that with RxJS, developers should think of themselves as 'plumbers', managing the flow of data. The video demonstrates reactive programming by subscribing to Observables and reacting to emitted values.

💡Backpressure

Backpressure in RxJS refers to the issue of an Observable emitting values faster than the consumer can handle. The script discusses strategies to handle backpressure, such as 'debounce', 'throttle', and 'buffer' operators, which help manage the flow of data to prevent overwhelming the consumer.

💡Memory Leaks

Memory Leaks in RxJS occur when subscriptions are not properly unsubscribed, causing the application to retain resources unnecessarily. The video script addresses this issue and provides strategies to prevent memory leaks, such as using the 'takeWhile' operator or manually unsubscribing subscriptions when they are no longer needed.

Highlights

RxJS is a powerful JavaScript library for handling asynchronous streams of data.

RxJS is more popular than Angular and only second to lodash in terms of daily npm downloads.

JavaScript alone doesn't provide everything needed to work with asynchronous data streams, which RxJS addresses.

Observables in RxJS are like pipes for data, allowing for subscription and notification of data changes.

RxJS is tree-shakable, meaning only the necessary code is imported, reducing bundle size.

Creating an observable involves calling it, which provides a callback function to notify subscribers of new data.

Subscriptions to observables are reactive, allowing for reactions to changes in observable data.

Observables can be completed, shutting them off and preventing further value emissions.

RxJS provides helper functions like 'of' to create observables from raw values or 'fromEvent' to create observables from DOM events.

Schedulers in RxJS can control whether observables are synchronous or asynchronous.

Hot and cold observables differ in their ability to have multiple subscriptions; cold observables create values upon subscription.

Subjects in RxJS are like hot observables with the ability to push new values to the stream.

Behavior subjects maintain a current value, ensuring that all subscriptions receive the last emitted value.

RxJS operators like 'map' and 'scan' can transform and accumulate values in an observable stream.

The 'filter' operator can be used to prevent certain items from being emitted in the stream.

The 'take' operator can control the number of values emitted from an observable before completion.

The 'tap' operator allows for triggering side effects within an observable pipe.

Back pressure in RxJS can be managed with operators like 'debounce', 'throttle', and 'buffer'.

The 'switchMap' operator allows switching from one observable to another based on a value.

Combining observables can be achieved with 'combineLatest' or 'merge', depending on whether you want to wait for all values or emit them as they come.

Error handling in RxJS can be managed with the 'catchError' operator, allowing for error interception and replacement with default values.

Memory leaks in RxJS can be prevented by unsubscribing from subscriptions or using operators like 'takeWhile'.

The 'takeUntil' operator can be used to stop a subscription when another observable emits a value.

Transcripts

play00:00

[Music]

play00:06

one of the most difficult but also most

play00:08

rewarding javascript libraries to learn

play00:10

is rxjs it's a tool that helps us

play00:12

control data as it flows through the

play00:14

dimension of time in today's episode of

play00:16

code that's notthat you'll learn ten

play00:17

fundamental concepts in rxjs and how to

play00:19

avoid the bad stuff if you're new here

play00:21

like and subscribe and leave me a

play00:23

comment below for a chance to win this

play00:24

t-shirt next week rxjs is getting pretty

play00:26

popular these days in fact it gets more

play00:28

daily npm downloads than angular

play00:30

reactive view and the only functional

play00:32

library that i'm aware of it's bigger is

play00:33

low - and the reason it's so popular is

play00:35

because javascript alone doesn't give us

play00:37

quite everything we would like to work

play00:39

with asynchronous streams of data we

play00:41

have promises but they only work with a

play00:42

single ASIC value so we use callbacks

play00:44

for real time streams but you've

play00:46

probably heard the term callback hell

play00:47

rxjs addresses these issues and gives us

play00:50

a powerful functional library for

play00:51

dealing with strings and when I say

play00:53

stream I'm talking about any data source

play00:55

that unfolds over the dimension of time

play00:57

things like data from firebase Dom

play00:59

events WebSockets file uploads etc the

play01:02

first thing you'll need to do is install

play01:04

rxjs I'm currently running version 6.4

play01:06

now I'm just using vanilla JavaScript

play01:08

with webpack but feel free to follow

play01:10

along with your favorite JavaScript

play01:12

framework the most fundamental class in

play01:14

rxjs is the observable you can think of

play01:16

it as a wrapper for some data that can

play01:18

be subscribed to and then the subscriber

play01:20

will be notified anytime the data

play01:21

changes when working with rxjs you

play01:23

should think of yourself as a plumber

play01:25

and I mean that in the most literal

play01:26

sense because an observable is

play01:27

essentially a pipe for data and rxjs

play01:30

gives you all kinds of tools to modify

play01:31

those pipes let's go ahead and create

play01:33

our first observable but first we need

play01:35

to import the rxjs library and there's a

play01:37

right and a wrong way to do this

play01:39

currently I'm doing it the wrong way by

play01:41

using import star as our X but that's

play01:43

going to cause the entire library to be

play01:45

bundled up in our code you can see down

play01:47

here we have a bundle size of 47

play01:49

kilobytes but rxjs is a tree shakable

play01:51

library which means we only have to

play01:53

import the code that we actually need so

play01:55

when working with rxjs you should only

play01:57

import the classes and operators that

play01:59

you actually need in your source code

play02:00

and by doing that we reduce our bundle

play02:02

size to less than 2 kilobytes now that

play02:04

you know that let's go ahead and create

play02:05

an observable from scratch now you won't

play02:08

normally create observables like this in

play02:09

your own code but it's a good exercise

play02:10

to understand what an observable is when

play02:13

we call observable

play02:14

it gives us a callback function that we

play02:16

can use to notify a subscriber with some

play02:18

new data this can be synchronous or

play02:20

asynchronous but basically every time we

play02:22

call next it's like emitting an event to

play02:24

the subscriber that they can listen to

play02:25

and react to now that we have our

play02:27

observable created we can create a

play02:29

subscription to that observable by

play02:31

calling subscribe on it

play02:32

subscribe takes a function that will be

play02:34

called every time the observable emits a

play02:36

new value and this is why they call it

play02:37

reactive programming because with your

play02:39

subscription you're reacting to changes

play02:40

in the observable data throughout this

play02:43

video I'm using my own helper method

play02:44

called print' which will react to each

play02:46

newly emitted item and print it to the

play02:48

Dom so we can visualize what's happening

play02:49

in the observable and if we open this in

play02:51

the browser you can see we get ABC

play02:53

logged one after the other another

play02:55

important concept to keep in mind is

play02:56

that observables can be completed which

play02:58

means they'll be shut off and no longer

play03:00

a net values if we had observer complete

play03:02

and then go back to the browser you can

play03:03

see that only a and B are emitted and

play03:05

that's because this stream has been

play03:07

closed if you think like a plumber

play03:08

creating the observable is like

play03:10

connecting a pipe to a water source and

play03:11

then subscribing is like opening the

play03:13

valve that lets that water out rxjs

play03:15

provides a bunch of helper functions

play03:16

that make it easier to create

play03:18

observables for example if we want to

play03:20

just create an observable of a raw value

play03:22

we can use of this we'll just take the

play03:24

value that you pass in and wrap it in an

play03:26

observable if we subscribe to this then

play03:27

we'll just get hello printed out in the

play03:29

console now the of function is very easy

play03:32

to mix up with the from function which

play03:34

takes an array promise or iterable and

play03:36

then emits each individual item from the

play03:38

observable we can see the difference by

play03:40

passing in a string which itself is

play03:42

iterable instead of emitting the entire

play03:43

string as one event it emits each

play03:45

individual character in that string

play03:47

another thing we can do is create an

play03:49

observable from events in the Dom using

play03:51

from event we first pass in a Dom

play03:53

element and in the event that we want to

play03:54

listen to if we listen to clicks on the

play03:56

document and subscribe to the observable

play03:58

we'll get an event every time we click

play04:00

on the page another thing we can do is

play04:02

set up an observable based on a time

play04:03

interval it takes the number of

play04:05

milliseconds as its argument and then

play04:06

will emit a number each time that

play04:08

interval passes now one thing that a lot

play04:10

of people don't realize is that rxjs can

play04:12

be synchronous or asynchronous and

play04:14

you'll probably never have to do this

play04:15

but you can control that behavior by

play04:16

modifying schedulers if you get lost in

play04:19

this next example I would recommend

play04:20

watching my async/await video which will

play04:22

teach you all about the event loop and

play04:23

JavaScript let's go ahead and define a

play04:25

string observable using of

play04:27

and then we'll just synchronously call

play04:28

our print method with world in this case

play04:30

rxjs is going to treat that observable

play04:32

as asynchronous value so the

play04:33

subscription will happen on the main

play04:34

thread therefore we get hello world

play04:36

printed one after the other you can

play04:38

change this behavior by modifying the

play04:39

schedule or of the observable if we pass

play04:41

in the async scheduler it will emit the

play04:43

value of the observable on the next

play04:45

iteration of the event loop this time in

play04:46

the browser we get world hello and again

play04:48

you'll probably never need to mess with

play04:49

that but I just want to give you an idea

play04:51

of what schedulers do the next thing

play04:53

we'll do is look at the difference

play04:54

between hot and cold observables I don't

play04:56

really like this terminology and I think

play04:58

the best way to think of it is hot

play04:59

observables can have multiple

play05:00

subscriptions whereas cold observables

play05:02

can only have one subscription cold

play05:04

observables don't actually create the

play05:06

underlying value until they're

play05:07

subscribed to will go ahead and create

play05:09

an observable from scratch and just have

play05:11

it generate a random number now if we

play05:13

subscribe to this observable twice

play05:14

you'll see that we get two different

play05:16

random numbers that's because that

play05:17

create callback function isn't called

play05:19

until the subscription is created but

play05:21

often in the real world that's not what

play05:22

you actually want a lot of times rxjs is

play05:25

valuable because you can share a value

play05:27

across multiple subscribers if you have

play05:29

an existing cold observable there are

play05:30

multiple ways to make it hot or in other

play05:32

words allow it to be broadcast to

play05:34

multiple subscribers now in this example

play05:36

only the first subscriber will get the

play05:37

actual value but what's often useful in

play05:40

the real world is to use the share

play05:41

replay operator which will cache the

play05:43

last value as well if instead we pipe

play05:45

and share replay one you can see that

play05:47

both subscribers will get the same

play05:48

random number now in my experience I'm

play05:50

not usually taking cold observables and

play05:52

making them hot instead I'm creating

play05:53

subjects or behavior subjects you can

play05:56

think of a subject as a hot observable

play05:58

but it has the added benefit of being

play05:59

able to have new values pushed to it in

play06:01

plumbing terms it's more like a pump

play06:03

where you can add new values to the

play06:04

stream after it's been created we can do

play06:07

this easily by just instantiating a new

play06:09

subject and then we can subscribe to it

play06:10

just like we've done with our other

play06:11

observables what's unique about it is

play06:14

that it has a next method that we can

play06:15

call to add new values to the stream now

play06:18

a potential gotcha with a regular

play06:19

subject is that you need to have the

play06:21

subscription setup before you start

play06:22

adding values to it you can see here in

play06:24

this first example we subscribe then we

play06:27

add two new values to it and then we set

play06:29

up a second subscriber and what you

play06:30

intuitively might think is that both

play06:32

subscribers will get the same values but

play06:34

that's not true for the second

play06:35

subscriber which will get nothing

play06:36

because it's subscribed late after the

play06:38

values were already at

play06:39

and that brings me to one of the most

play06:41

useful things in rxjs which is the

play06:42

behavior subject it's similar to the

play06:44

subject we just looked at except it has

play06:46

the concept of a current value this

play06:48

means the last emitted value will be

play06:50

cached similar to how we set it up with

play06:51

share replay earlier but most

play06:53

importantly it means that every

play06:54

subscription will always receive a value

play06:56

even though our second subscriber came

play06:58

in late it still gets the last emitted

play06:59

value in the stream and that tends to be

play07:01

a very powerful feature when doing

play07:03

things like state management and

play07:04

front-end applications at this point

play07:06

we've only been talking about creating

play07:07

observables now it's time to look at

play07:09

operators which help you control the

play07:10

flow of data going through your

play07:12

observables there are a ton of operators

play07:14

built into rxjs so we'll just look at a

play07:16

handful of some of the most popular ones

play07:18

first we'll create a source observable

play07:20

the NIEM it's the integer is 1 through

play07:21

10 you can compose multiple operators

play07:23

together by using a pipe and just like

play07:26

it sounds your data will flow through

play07:27

this pipe and then be modified by each

play07:29

function or operator in the pipe if we

play07:31

subscribe to the empty pipe it just

play07:33

emits the values of 1 through 10 to take

play07:35

the input and simply transform it to a

play07:37

new output you can use the map operator

play07:39

for example we can take each number and

play07:41

then raise it to the power of 2 now the

play07:43

observable emits the square of the

play07:45

initial numbers another thing we can do

play07:47

is accumulate values as they flow

play07:48

through the observable similar to a rate

play07:50

reduce if we want to keep a running

play07:52

total of all the values that were

play07:53

emitted in this observable we can use

play07:55

the scan operator and then add the

play07:56

current value to the accumulated value

play07:58

now each emitted value gets added on top

play08:00

of the previous one an important thing

play08:02

to keep in mind here is that the order

play08:03

of operation matters for example if we

play08:05

move the scan operator before the map

play08:07

operator we're going to get different

play08:08

results because the underlying math is

play08:10

now different so that's how you

play08:11

transform values but another useful

play08:13

operator is filter which prevents

play08:14

certain items from being emitted in the

play08:16

stream for example if we only want

play08:18

values that are greater than 10 we can

play08:19

use the filter operator and that will

play08:21

only emit values that meet this

play08:22

condition and now we only see values

play08:24

that are greater than 10 printed in the

play08:26

UI another thing we can do with

play08:27

operators is tell the observable to

play08:29

complete for example if we pipe in take

play08:31

3 it will only emit three values from

play08:33

this observable then complete it the

play08:35

next thing I want to show you is an

play08:36

operator called tap which allows you to

play08:38

trigger side effects from inside the

play08:39

observable pipe in all the examples so

play08:42

far I've been printing values to the

play08:44

screen by using the callback in the

play08:45

SUBSCRIBE method but that only gives us

play08:47

access to the value at the end of the

play08:49

pipe the most simple use case that

play08:51

you'll find is just console logging at

play08:52

different

play08:53

points within the observable pipe the

play08:54

pipe modifies things from top to bottom

play08:56

so if we add a tap to the very beginning

play08:58

it's going to print the initial value

play09:00

and if we map it to something else and

play09:01

add another tap after that it's going to

play09:03

print a different value and you can use

play09:05

tap to trigger more complex side effects

play09:07

for example you might want to save a

play09:09

value from the observable to a back-end

play09:10

database if you're using something like

play09:12

firebase you'll probably wanna use an

play09:13

async function so basically it just

play09:15

gives you a context to tap into the

play09:17

observable and do something another term

play09:19

you might hear with rxjs is back

play09:21

pressure and basically that means you

play09:22

have an observable that's emitting way

play09:24

more values than you actually need we

play09:26

can simulate this in the code by

play09:27

listening to the mousemove event on the

play09:29

Dom moving the mouse across the screen

play09:31

will cause the observable to emit

play09:32

multiple events every second rxjs has

play09:34

several operators that can help us with

play09:36

this situation the first strategy we'll

play09:38

look at is to debounce the events ad

play09:40

bounce will filter out all events until

play09:41

they have stopped happening for a

play09:43

certain period of time in this case

play09:44

8,000 milliseconds ad bounce is really

play09:47

useful for something like a type-ahead

play09:48

where you don't want to make an API call

play09:49

until the user is done typing you can

play09:51

see here if we mouse around for a little

play09:53

while nothing happens then if we stop

play09:55

our event will be emitted after one

play09:56

second

play09:57

an alternative to ad balance is a

play09:58

throttle it will emit the first value

play10:00

but make sure that no additional values

play10:02

can be emitted until a certain time

play10:03

period has passed if we go back to the

play10:05

demo and start moving around at the very

play10:07

most we'll get one event emitted per

play10:08

second these operators are alleviating

play10:10

the back pressure but they're also

play10:12

filtering out a lot of data if we want

play10:14

to keep all the data but just not listen

play10:15

to it all at once we can use a buffer

play10:17

this will collect all the events into an

play10:19

array and then only emit them when they

play10:21

get to a length of 20 now we're going to

play10:23

switch gears to another very important

play10:25

operator called switch map this allows

play10:27

you to start with one observable and

play10:29

then switch to another one which is very

play10:30

important when we're talking about

play10:31

relational data for example if you're a

play10:34

firebase user you probably have an

play10:35

observable of a user logged into your

play10:37

app and then you might want to switch to

play10:39

another observable of some information

play10:41

about that user in the database we can

play10:43

simulate that in our code by creating an

play10:45

observable of an object and then I'll

play10:47

create a function that returns an

play10:48

observable of some information based on

play10:50

a user ID we can't call this function

play10:52

until we have a user ID so the question

play10:54

becomes how do we get the user ID out of

play10:56

the observable the naive way to do this

play10:58

is to nest subscriptions within each

play10:59

other so first we subscribe to the user

play11:02

that will give us the user ID then we

play11:03

create another subscription inside of

play11:05

that call

play11:06

for the orders that code will actually

play11:08

work but there's a better way to do this

play11:10

instead we'll start with our user

play11:11

observable to compose a new observable

play11:14

called orders we first add a pipe to the

play11:16

user and then we use the switch map

play11:18

operator which will give us access to

play11:20

the user ID and then we just returned an

play11:22

observable from it and you can also

play11:24

return a promise or an array here as

play11:25

well so if you ever have one value that

play11:27

depends on another value switch map

play11:29

might be the operator that you're

play11:30

looking for but there might be other

play11:31

cases where you have multiple

play11:32

observables that you just want to

play11:34

combine into a single stream we'll look

play11:36

at two different functions here called

play11:38

combine latest and merge and keep in

play11:40

mind these are not technically operators

play11:41

so we import them directly from rxjs

play11:44

I'm creating a cold observable of a

play11:46

random number and then I'm creating a

play11:47

second observable that just adds a delay

play11:49

to that random number first we'll use

play11:51

combined latest and it takes an array of

play11:53

observables and it will wait for each

play11:55

observable - you made a value and then

play11:57

he met everything together as an array

play11:58

even though the random numbers are going

play12:00

to emit something right away it's going

play12:02

to wait for that delay to resolve into a

play12:04

value before it emits anything then if

play12:06

any of the observables emit anything

play12:07

after that it will emit everything again

play12:09

as an array in other words it gives you

play12:10

the current state of every observable in

play12:12

this array so initially it's blank for

play12:14

one second waiting for that delay and

play12:16

then it emits out the four random

play12:17

numbers in many cases though you don't

play12:19

want to wait for that delay so instead

play12:21

you can use merge which will just emit

play12:23

each value one by one as it comes in

play12:25

through the stream merge doesn't care

play12:27

about the array position of the

play12:28

observable it only cares about when it

play12:30

emits it in the context of time so it

play12:32

emits the first three values and in the

play12:34

delayed value a second later another

play12:36

thing you might be wondering is how to

play12:37

catch errors in the context of a stream

play12:39

you have a lot of flexibility here

play12:41

but one of the most common strategies is

play12:43

to catch the error and then replace it

play12:45

with some other value we can do this

play12:47

easily with the catch error operator it

play12:48

can intercept the error and then you met

play12:50

some other default value out of the

play12:52

stream and one thing that's really nice

play12:53

about rxjs is you can easily retry

play12:55

things by just piping and the retry

play12:57

operator I'm not going to get into it

play12:59

here but it's super useful when working

play13:00

with HTTP calls

play13:01

first of all push a regular value and

play13:03

then an error to the subject if we don't

play13:05

catch the error

play13:06

we'll get this uncaught error in the

play13:07

console but by using the catch error

play13:09

operator we can handle it in the

play13:10

background and then provide some useful

play13:12

information to the user and the front

play13:14

end now if you're a good plumber then

play13:16

you shouldn't have pipes that leak and

play13:17

by that I'm talking about memory

play13:18

weeks there are two main ways to prevent

play13:21

memory leaks with rxjs

play13:22

the first way is to unsubscribe from

play13:24

your subscriptions take for example this

play13:26

interval this interval is going to run

play13:28

forever so if we don't close the

play13:30

subscription it's just going to create a

play13:31

memory leak in the background one

play13:33

potential way to handle this is to

play13:34

create a variable for the subscription

play13:35

and then call subscription unsubscribe

play13:38

at some other point in the code this

play13:39

will stop the leak because we can see

play13:41

here the observable only emits 10 values

play13:43

but there's actually a better way we can

play13:44

do this we can pipe in the take while

play13:46

operator to the interval itself and that

play13:48

will tell it to emit values only while a

play13:50

certain condition is true when that

play13:52

condition becomes false it will stop

play13:54

your minion values therefore preventing

play13:55

the memory leak and we don't need to

play13:57

manually unsubscribe anywhere in our

play13:59

code that works well in a lot of

play14:00

situations but sometimes you want some

play14:02

other observable or subject to be the

play14:04

thing that triggers the subscription to

play14:06

stop for that we have the take and tell

play14:08

operator and it takes an observable as

play14:11

its argument and when that observable

play14:12

emits something it will cancel the

play14:14

subscription on the source for example

play14:16

if we wanted to set a timer for two

play14:18

seconds on this interval we could do

play14:19

that by using take and tell with a timer

play14:21

observable when the timer finishes it

play14:23

will complete the interval and then end

play14:25

the subscription I'm gonna go ahead and

play14:26

wrap things up there we barely just

play14:28

scratch the surface with rxjs so let me

play14:30

know what you want to see next in the

play14:31

comments if this video helped you please

play14:33

like and subscribe thanks for watching

play14:34

and I will talk to you soon

play14:37

[Music]

Rate This

5.0 / 5 (0 votes)

Связанные теги
RxJSReactive ProgrammingJavaScriptObservablesOperatorsAsynchronous DataData StreamsFunctional LibraryError HandlingMemory Leaks
Вам нужно краткое изложение на английском?