Podchaser Logo
Home
765: JS Promises Fundamentals - Part 1

765: JS Promises Fundamentals - Part 1

Released Monday, 6th May 2024
 1 person rated this episode
765: JS Promises Fundamentals - Part 1

765: JS Promises Fundamentals - Part 1

765: JS Promises Fundamentals - Part 1

765: JS Promises Fundamentals - Part 1

Monday, 6th May 2024
 1 person rated this episode
Rate Episode

Episode Transcript

Transcripts are displayed as originally observed. Some content, including advertisements may have changed.

Use Ctrl + F to search

0:00

Who. Are going to sent a fax

0:02

today. We've got a first of three

0:04

shows on Promises Deep Dive. So I

0:06

was driving home from dropping off my

0:09

kids at school today and I thought

0:11

like. Hung. Out to a showy

0:13

what should we do? you know, and I

0:15

haven't keeping notes on. Just like all of

0:17

these things. That. Surround working

0:19

with promises in javascript I realized

0:22

like man, there's actually quite a

0:24

bit. Too. Or. He

0:26

was promises and or gets acting

0:28

him and flow control and all

0:30

that. So this is going to

0:32

be the next three Mondays are

0:34

going to be all hasty treats

0:36

on deep dive into promises are

0:38

today. We've got sort of an

0:40

introduction understanding how promises work in

0:42

awaiting them in different ways to

0:44

create in listen for a promise,

0:46

resolve, then a second they were

0:48

going to have one on canceling

0:50

promises, helper methods and error handling

0:52

strategies. Her Hattie, Hattie You specifically

0:54

deal with errors. In a

0:56

nice way for your application with

0:58

promises. I'm and than the last

1:01

one we have is getting into

1:03

concurrency queuing, flow control thatch cancelling

1:05

them and difference which is a

1:07

new A P I in in

1:09

the browser so buckle up for

1:11

the next three weeks and we

1:13

are all kinds of. I promise

1:15

you are going to enjoy it.

1:17

I promise you as about to

1:19

make that same joke as yeah

1:22

good or yeah let's see how

1:24

many promise jokes can we make.

1:26

In the next three weeks and if

1:28

you want to see our the errors

1:30

in your application you'll want to check

1:32

out Century ad Century.i owe Forward/syntax you

1:35

can sanjay get two months of free.

1:37

Century is just a really incredible to

1:39

over now only tracking your performance making

1:41

true application has no bugs but even

1:44

just seeing what goes wrong when something

1:46

goes wrong because things go wrong all

1:48

the time when we're coding and you

1:50

don't want a production application out there

1:53

that while you have no visibility into

1:55

in case something. Is blowing up and you

1:57

might not even know it so had already

1:59

century.iowa. again, we've been using

2:01

this tool for a long time and

2:04

it totally rules. All right, I

2:06

think it's a great idea though because you know, I remember

2:09

when I first learned about promises back

2:11

when they weren't in the browser you

2:13

had to use q or bluebird or

2:15

one of those right? Yeah, I

2:17

remember being very confused about why

2:20

they're a big deal. What makes them

2:22

interesting? How is it different than something like

2:25

a callback function? What's the

2:27

deal with promises? So I think this will

2:29

be a really great episode and in this

2:31

episode and specifically, yeah, we're getting

2:33

into promises 101 creating and

2:35

waiting on promises. So I think we can

2:37

start this off with the

2:39

first question.

2:42

What is a promise Wes? A

2:44

promise in JavaScript is an object

2:46

that represents the eventual completion of

2:48

some data and that's different than

2:51

a regular variable or a function

2:53

return in JavaScript because normally

2:55

the result of a promise

2:58

is returned immediately. You get something right

3:00

away but a promise is sort of

3:02

an IOU, a promise

3:04

that eventually at

3:06

some point in the future, I will

3:10

give you some piece of data

3:12

or I'm going to fail which

3:14

is called rejecting. So again, a promise

3:16

is a future agreement

3:19

that some data will be returned

3:21

to you. It's a commitment.

3:23

It's a commitment. Yeah. And

3:28

I thought like let's just kick it off with

3:30

just some common examples of what a promise would

3:32

be. I know most people

3:34

listening sort of understand what a promise

3:36

would be but let's talk about any

3:39

type of data that can be returned from a promise

3:41

which is anything. The most

3:43

common one being you want to take this one?

3:46

Yeah, I think the one that most people have used is

3:48

fetch calls. If you go off

3:50

and you know, there used to be libraries

3:52

and now we have a standardized fetch API.

3:55

If You go off to grab some data from

3:57

anywhere and you're most likely using Fetch. That

4:00

you've ever tried to access that data

4:02

immediately, You'll know that in the returns.

4:04

A promise. It. When. You got

4:06

to do fetch it. It doesn't know how long

4:08

that's going to take it has. I'm gonna go

4:11

get some data. I'll be right back. And.

4:13

Then nice A or it led me. To.

4:16

Wait for that limit out war. we win.

4:18

The data does come back or perhaps perhaps

4:20

you failed to get to the store. Ah,

4:22

then using you know, bring their data back

4:24

and now we can do something with it.

4:26

So he got off to it as trip.

4:28

To. The Store. You've now come back with

4:30

the goodies that you you ordered. Yes,

4:33

And that promises being a

4:36

feature of the language has

4:38

been. An Amazing like

4:40

I know, I'm Most languages have sort

4:43

of the idea of a promise or

4:45

or a way to do this type

4:47

of work by an him. Being able

4:50

to have it as a primitive in

4:52

the language means that you can mix

4:54

and match. Anything that

4:56

returns a promise and you can work with

4:59

them together. This is one thing when there's

5:01

a new thing called the from there have

5:03

been added to promises and it's not really

5:05

like a new thing, but it's It's a

5:08

new A T I that makes working with

5:10

differ. It's a little bit easier in a

5:12

lot of Iraq. Why are they adding all

5:14

the garbage? Why don't you just go in.

5:16

Use this library that already didn't really well

5:19

and often I'm in that camp like nam.

5:21

Maybe we don't need a very opinionated way

5:23

to do this and language bites with with

5:25

promises Being able to. Have a single

5:27

type. Previously. It was like

5:30

Scott said, you have to use Blue

5:32

Bird or Sank or call backs. It

5:34

was very hard to say I want

5:36

me and I work with this database

5:38

adapter and I'm going to be working

5:41

with this A P I that does

5:43

validation or or does a bunch of

5:45

chewing and getting those to work together

5:47

was always kind of frustrating and now

5:49

that we have, we've had them in

5:51

that the browser for many, many years.

5:54

it's much easier. Another example of promises

5:56

would be a database query or an

5:58

insert. command pretty much any database

6:00

ORM that you're using these days if

6:03

your database is not going to solve return

6:06

immediately and even if it

6:09

did that's something called a

6:11

synchronous request or a blocking request and

6:13

what that would do is it would

6:15

actually lock up the rest of your

6:17

application from running. So if you it's

6:19

very hard to actually write code these days where

6:22

you create a blocking circumstance

6:24

but you could if you if

6:27

you did have a blocking database

6:29

right you could run into

6:31

the situation where your server is handling incoming

6:33

requests from the user and if

6:36

you have a insert

6:38

that takes two seconds then all of a sudden you're

6:40

blocking any requests that are coming in

6:42

for two seconds and that's that's sort of a

6:44

bad day. So database queries

6:46

every ORM that you work

6:48

with will return to you a promise and then you can

6:50

sort of just wait for that to successfully

6:53

give you the message say I saved the

6:55

data or resolves to the query of the

6:57

data that's been returned to you. Yeah if

6:59

you if you notice a pattern here we're

7:01

basically anytime something could

7:03

be blocking we use

7:06

a promise so that way it takes something that

7:08

could be blocking and makes it so it does

7:10

not block the execution of other things which is

7:12

one of the reasons why we have to do

7:14

the whole the whole then thing

7:17

with promises that we'll get into. Another

7:19

thing could be requesting the

7:21

user's permissions for things like a webcam

7:24

right the reason why these have to

7:26

be returned as promises

7:28

because you're again you're waiting for

7:30

something to come back from the user's computer

7:32

whether that is prompting them to do a

7:35

permissions acceptance or whatever. And

7:37

then a little wait function is

7:40

example of a promise that you might write yourself

7:42

so you might want to wait for a certain

7:44

number of milliseconds you might want to wait for

7:46

somebody to click on something you

7:49

might want to wait for something to show

7:51

up on the page that's very popular in

7:54

like React testing library where you want

7:56

to stop your code from running you wait

7:58

for something to show up in the page and

8:00

then when that thing is on the page, it will resolve.

8:03

We'll talk about that in just a second and

8:05

you can continue on with your life. So

8:09

promises have two ideas here is

8:11

that when you create a promise,

8:14

you get the option to

8:16

resolve that promise or reject

8:19

that promise. Resolving a promise

8:21

is successfully returning the data

8:24

that that promise has set

8:26

out to go get or

8:28

to go fetch for

8:30

you or to you would resolve after somebody

8:33

clicks a button. That's a successful outcome of

8:35

a promise is called the resolve and

8:37

a negative outcome of a promise

8:40

is called a reject. And often

8:42

you will call reject in your

8:45

promises when you something

8:48

goes awry. Right. That

8:50

that database item didn't save correctly. The

8:52

user did not actually give me access

8:54

to their webcam. Something

8:56

happened inside of this promise where

8:58

there was an error that happened

9:00

because of a different library. Those

9:03

are reject cases. Yes. And

9:05

I don't think this necessarily fits in there,

9:07

but there's also so you

9:10

resolve a rejected promise and those

9:12

things connect very firmly to when

9:15

we're working on promises. We'll talk about this

9:17

in a bit, but that does connect directly

9:19

to the then right. The

9:21

then method is called once a promise

9:23

has been resolved. The catch method has

9:26

gets called when something is rejected and

9:28

then finally gets called no matter what.

9:31

Well, then we'll talk about those more in a second.

9:33

So next step is creating

9:35

promises. So how do you create

9:37

your own promise? But oftentimes we're

9:39

consuming promises, right? We're using a

9:41

dot then we're using a async

9:43

await. We're not necessarily writing

9:46

them, but you can write your own

9:48

promises using new promise

9:50

and you can create a promise. And

9:52

that gives you a callback where

9:54

you can use the resolve or reject

9:57

methods to like Wes mentioned a moment

9:59

ago. either resolve and

10:01

complete the promise or reject and

10:03

fail the promise. Yeah, you are

10:05

often creating your own promises when

10:08

you want to bundle together a

10:10

bunch of functionality and

10:12

often you'll have like nested promises.

10:14

So you might have a promise

10:17

called create user, right? And

10:20

in that create user promise

10:23

or a function that returns a promise, I

10:25

promise I will go and create the user

10:27

and return to you the

10:29

actual user once I'm done. But inside of

10:31

that, you may be doing several things, right?

10:33

You may be doing some sort of validation,

10:35

you might be checking if they have already

10:38

been signed up, you might be hashing their

10:41

password to store in a database, you will be

10:43

actually saving that user to the database,

10:46

you'll be creating timestamps, you'll be maybe

10:48

creating some items that are

10:50

related to that user, setting a bunch

10:52

of permissions and all of those things

10:54

need to happen inside of your promise.

10:56

They can also often chain them together

10:58

and then when you're successfully done, you

11:00

resolve it. If there's an error anywhere

11:02

along the way, you can reject

11:05

that promise and say, this

11:07

is explicitly what has happened. There's

11:10

a new method which I'll talk a bit

11:12

more about in a future episode, this idea

11:14

of deferreds. But promise.withresolvers is

11:16

another way to create a

11:19

promise and that will

11:21

return to you the promise itself

11:23

but also the reject and resolve

11:25

methods at a top level. And

11:28

this can be handy if you want to pass

11:31

the resolver and reject methods to other

11:33

parts of your application rather than doing

11:35

your work inside of the promise itself.

11:38

And then the third way we have

11:40

for creating a promise and this is

11:42

quite honestly the most common way these

11:44

days is you mark a function, a

11:47

sink. And instead of creating

11:49

a new promise and putting all of

11:52

your code inside of a promise callback,

11:54

which does have use cases, you simply

11:56

just Create a function, you mark

11:59

it with this... The key word

12:01

a sink in front of it

12:03

on Media Li that function changes

12:05

from a function that will return

12:07

you data right away turns into

12:09

a function that will return a

12:11

promise. That. Overturned data at some

12:13

point in. The kind of. the cool

12:16

thing about a sink functions is that

12:18

inside of addressing function you can simply

12:20

just return a value. You

12:22

can have other promises and side of

12:24

their and if you return either a

12:27

value or a promise you don't have

12:29

to use the resolves method, you simply

12:31

just return and because the the function

12:34

has been marked as the think it

12:36

will have that. It'll work just

12:38

fine. The same thing with rejecting you

12:41

don't have to explicitly reject. You can

12:43

throw an error which you may be

12:45

used to already in say up. Throw.

12:48

New error. User. Email

12:50

has already been registered. Yeah.

12:53

And here's a small little thing

12:55

for people who find themselves doing

12:57

this: if your function returns a

13:00

promise. Where. You

13:02

don't wanna do is you don't want to

13:04

mark the function as a saying in in

13:06

a way that promise and then return the

13:08

result. You. Just return the

13:10

promise from that function. And

13:13

you returning a promise from the function

13:15

rather than having to create a new

13:17

promise and into it that way So.

13:19

Like. I mentioned within any get into like

13:22

the waiting on a promise bit of this

13:24

as a coma I was, I, oh, I'm

13:26

reading, I had a about that. You

13:28

sometimes do have a think functions that

13:31

return promises and and the use case

13:33

for that is sometimes you want to

13:35

first await something inside of that. And

13:38

then. You may want to

13:40

return the actual promise itself. From that

13:42

functions there's no harm in like sort

13:44

of double wrapping your promises. So if

13:46

you were to have an a sink

13:49

function that returns a promise itself you

13:51

not going to get into any weird

13:53

like nested then set that will be

13:55

an issue for you. Do. You think

13:57

there is a any sort of performance implications there.

14:00

I don't know if there is. I'm just wondering. I don't

14:02

think so. Often I have tweeted

14:04

screenshots of code that I've written and I'll just

14:06

mark a function as a sync and then I'll

14:08

refactor it to return a promise. And

14:11

sometimes there's an unnecessary a

14:14

sync on there, which is why I like the ESLint

14:16

rule. I will be like, you

14:18

didn't await anything inside of this. What are you

14:20

doing? Marking it as a sync. But

14:22

I don't think there is. At

14:25

least I don't know of any

14:27

performance downside to having

14:29

a function marked as a sync if you are

14:32

returning a promise. Word.

14:34

All right. Well, let's talk about waiting on a

14:36

promise, then, because like we mentioned, a promise is,

14:38

you know, the commitment to come back and, you

14:41

know, I'm promising to go to the store and

14:43

get some candy cigarettes. When I come back, I

14:46

better have those candy cigarettes. Do you remember those,

14:48

by the way? Did you ever get those

14:50

in Canada? Yeah, it's pretty wild that

14:52

we just like had cigarettes and they're

14:54

like red on the tips like clearly you're trying

14:57

to make these fake cigarettes. But I said you're

14:59

supposed to like keep them in your mouth. I

15:01

just chomped them up. That's what I did. And

15:03

they're like, I can't I can't do that. All

15:07

right. Well, let's talk about waiting on those

15:09

promises, right? So the main way that a

15:12

lot of people have done it is with

15:14

a dot then method. So instead of using

15:16

a sink await or anything like that, you

15:18

have your promise. Then you say

15:21

you have a function call, right, obviously, and

15:23

then you chain a dot then to the end

15:25

of that dot then has

15:27

a callback. And then that callback has

15:30

the data that's available to you

15:33

if that promises resolved correctly. If

15:36

the premise rejects, you would then need

15:38

to also chain a dot. Catch.

15:41

I don't know why.

15:44

I don't know why I said that, you

15:46

know, apprehensively. You then need to change a

15:48

dot catch in which the error will be

15:50

available in the call that function. And then

15:52

there's also a third one

15:54

that a lot of people don't use, which is

15:57

finally, which this will go no matter what. So

15:59

if you find. yourself duplicating some logic

16:01

maybe like you're waiting for a value

16:03

and then you're setting a state toggle

16:05

based on that value if that state

16:07

toggle is toggled no matter what if

16:09

there's an error or a success

16:11

state you can put that in your

16:14

finally so the finally is gonna run

16:16

no matter what after the catch and

16:18

after the then yeah

16:20

that's that's really handy if you like

16:22

have like a loading state and

16:24

you need to turn the loading

16:27

state off in both cases right

16:29

and after a successful return or

16:32

on error I want to turn the loading state off that

16:34

the finally is super handy for that

16:37

and I quite honestly I don't see it used

16:39

all that often so I think

16:42

I should maybe start using a little bit more

16:44

myself so the

16:47

dot then is a pretty common

16:49

way to do it and then we

16:51

also have the ability to await promises

16:53

so when you're in a function that

16:56

is marked as a sink you

16:58

can sort of pause that function

17:00

from running and once

17:03

the promise resolves itself you can

17:06

continue ongoing so it's a beautiful

17:08

API because you can simply just

17:10

say like const user equals await

17:14

create user whereas the create user function would

17:16

return a promise putting an await in front

17:18

of it will will sort

17:20

of unwrap the promise it will wait for

17:22

the promise to resolve and give you the

17:25

actual data at the end of the day

17:27

await also is used for generator functions but

17:29

we're not getting into that in the promise

17:31

episode so I in

17:33

most cases I would say most people

17:35

use the async

17:37

await API simply because it reads

17:39

a lot nicer we'll

17:41

talk a little bit more about error handling and how

17:43

to mix and match them there are use

17:45

cases where you still want to use the dot then chaining

17:49

is a really nice one instead of just doing

17:51

await await await some people like to chain then

17:53

then then onto one another

17:56

the other one being that sometimes

17:58

you want to listen for

18:00

when something is resolved, but keep

18:02

the function going while you're

18:04

waiting for it. So a very common use

18:07

case that I've seen

18:09

is you want to go off

18:11

and fetch something. And then the next

18:13

line below that, you wanna set up like an

18:15

event handler for when somebody clicks

18:18

something or when a specific event happens. If

18:20

you were to await that fetch request, the

18:22

event handler would never run until, because

18:25

you're essentially pausing the use case. Same thing

18:27

with streams as well. That's a pretty common

18:30

use case where, all right, I'm

18:32

gonna set up this stream and

18:35

I'm gonna resolve once it's actually finished. So

18:38

what do you use, Scott, in most cases? Do

18:40

you default to sync await? Yeah,

18:42

my default is, it is

18:45

funny, because sometimes it feels haphazard in which I'll

18:47

be like, oh, I'm not inside of an async

18:50

function. I don't feel like making this function

18:52

async. So I'll just throw a dot then

18:54

on there. To

18:56

me, it depends on what I have to do with that

18:58

data. The thing that's always bugged me

19:01

about the then methods is that

19:03

you're now going another

19:05

layer deep, right? If

19:07

you wanna access that data outside of the premise, you

19:09

have to create a variable and

19:11

pass it in and worry about the

19:14

default values before and after the premise

19:16

return. So almost always I'm using await

19:18

just because it reads more like how

19:20

I would expect it to work and

19:22

then I can access the values where

19:24

I want to access them. All

19:27

right, wait for the value, it's there. Now

19:29

I can do something with it. But there

19:31

certainly are times where I am using a

19:33

catch or a dot then as well. I do

19:35

use a dot catch even

19:37

on await instead of doing a try catch now.

19:41

Yeah, that's something we have coming up in

19:43

the next one, which is error handling strategies

19:45

of like mix and matching. I

19:47

personally do that as well as I await, but

19:50

I use a dot catch to catch

19:52

the error in most cases. Chaining

19:54

the dot thens onto each other. And I should

19:56

say the way that this works is if you

19:59

have a dot catch, Then if

20:01

you return another promise from that dot

20:03

then you can chain them Indefinitely

20:06

and put a single dot catch at

20:08

the end of it any errors

20:10

that happen along the chain Where that

20:12

becomes an issue is then you have your a weird scope?

20:15

Which is hard and it's also really hard to like

20:17

pass data between the two of them So

20:19

if you have one promise

20:21

that fetches the weather and then another promise

20:24

that saves the weather to the database You

20:27

find yourself having to modify Functions

20:30

so that they'll accept the incoming

20:33

weather data and then that's

20:35

really frustrating because Now

20:37

if you want to comment one of them out Then you

20:40

have to change the signatures again, or

20:42

you create like a variable that's outside the scope

20:44

of the dot then and you sort Of update

20:46

it that's annoying because now you have like an

20:48

undefined variable for a short amount of time and

20:50

you have type script That's a bit tricky. So

20:53

yeah, I like I like the

20:55

the I I

20:58

Think await much better. The only time like

21:00

I'll mix and match them is often with

21:02

the dot fetch I'll

21:04

have the await whatever and if you

21:06

have to get Jason back, you know

21:08

It's Jason the fetch has like a

21:10

double promise thing, which we'll explain in

21:12

the in the next episode Sometimes

21:14

I'll just chain a little dot then on top of

21:16

it But

21:19

I think that's that's all we have for

21:21

the first episode again That was pretty high

21:23

level of explaining promises in the next episode.

21:25

We're going to get into Canceling

21:28

promises a boarding promises

21:30

some of the promise helpers, which

21:33

is all all settled Finally any

21:35

and race as well

21:37

as five different ways to handle

21:40

error handling strategies Sick.

21:43

I look forward to your promise of

21:45

future episode promise. It will be good.

21:47

Please. I can't wait You

Rate

Join Podchaser to...

  • Rate podcasts and episodes
  • Follow podcasts and creators
  • Create podcast and episode lists
  • & much more

Episode Tags

Do you host or manage this podcast?
Claim and edit this page to your liking.
,

Unlock more with Podchaser Pro

  • Audience Insights
  • Contact Information
  • Demographics
  • Charts
  • Sponsor History
  • and More!
Pro Features