Podchaser Logo
Home
771: Promises: Error Handling, Aborts, and Helper Methods - Part 2

771: Promises: Error Handling, Aborts, and Helper Methods - Part 2

Released Monday, 20th May 2024
 1 person rated this episode
771: Promises: Error Handling, Aborts, and Helper Methods - Part 2

771: Promises: Error Handling, Aborts, and Helper Methods - Part 2

771: Promises: Error Handling, Aborts, and Helper Methods - Part 2

771: Promises: Error Handling, Aborts, and Helper Methods - Part 2

Monday, 20th 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

Oh. I come to syntax

0:02

in this episode work to be taking

0:04

a part to to our series on

0:06

Promises and in this video or to

0:08

be talking about error handling we're going

0:10

to be talking about a boarding a

0:13

problem as helper methods and more. So

0:15

ah yeah we're going to continue our

0:17

our talk on promises and after this

0:19

when I think you'll never a great

0:21

idea about a little bit more in

0:23

terms of how to use them beyond

0:25

just the basic. So many not got

0:28

dramas. I. Promise you're going to

0:30

have a good idea where? Okay. Well

0:34

I promise you my name is Scott

0:36

to Lynskey and I'm from Denver with

0:38

me. As always is West passwords up

0:40

wears a not too much. I promise

0:43

that if you have issues with their

0:45

promises you're going to want to check

0:47

out Century cause center is gonna tell

0:49

you when your promises are thrown. Maybe

0:51

when they're the have an on caught

0:54

reject in one a your promises that

0:56

you weren't expecting can tell you I

0:58

myself am. Node used to have this thing called.

1:01

Know. Use the catchier uncap promises And

1:03

they warned for years that they're going

1:05

to turn it off. And. I

1:07

said. Yeah. Yeah to him.

1:09

One day masters my server crashed and

1:11

whenever my server crashes I get a

1:13

little century alert and I get an

1:15

email about it and I logged in.

1:18

I thought oh why do my server

1:20

crash and I looked at the center

1:22

air it was a fetch quest than

1:24

I had not been are no it

1:26

wasn't effect yet whether fetch requests but

1:28

it was a post so as posting

1:31

some data to a third party service

1:33

that service had an outage. And.

1:36

Because it was on handled. I.

1:39

Didn't catch their. Part. My

1:41

entire server crashed which is unreal

1:43

that I could crash entire server

1:45

just with the a single fetch

1:47

requests. But that happens and center

1:49

is able to am tell me

1:52

exactly what happened. I fix it

1:54

and like three minutes. So check

1:56

it out, Century.i'll check it out.

1:59

dick Well, let's get

2:01

into the first section of this

2:03

episode. We're going to be talking

2:06

about canceling promises. So you

2:08

have a promise that goes off and

2:10

like, I'm sending, or you're

2:13

sending me to the store, right? The

2:15

promise is that I'll return with the stuff. At

2:18

any given point, you can call me

2:20

up and say, hey, Scott, come

2:22

back. Yeah. Cut it out.

2:25

Stop doing what you're doing. I found the

2:27

cheese in the fridge. We don't need any

2:29

more cheese. Or it's a good way. You

2:32

can reject a promise at any time. So

2:35

that is entirely up to you. And

2:38

you can return with

2:40

the resolve or reject methods at any

2:43

time as well. You

2:45

basically have control over the

2:47

full process throughout which you're

2:49

working with your promise. Yeah.

2:52

Inside of a promise, you can, like

2:54

we said in the last episode, you get your

2:57

resolve, you get your reject methods and you can

2:59

do whatever you want with those. And

3:01

often what that includes is

3:03

you have some logic inside of your promise

3:05

that says, given

3:07

these use cases, maybe after

3:10

I've tried clicking the button

3:12

six times and it doesn't work, then

3:14

reject. Or after pretty common is you

3:16

want to put a five second timeout

3:19

on a promise. Say after

3:22

five seconds, if the thing doesn't come back

3:24

with data or after five seconds, if the

3:26

user hasn't clicked this button, then we need

3:28

to do something in order

3:30

to show that you'll catch the reject

3:32

in that case. So that's

3:34

an example of when you would want to put

3:37

the logic inside of a promise. Also

3:39

we have promise.withResolvers. Again,

3:42

we'll talk about them a little bit more

3:44

in the next episode. It's called deferred. But

3:47

essentially promise.withResolvers will give you the promise,

3:49

but it will also give you the

3:52

resolve and the reject methods outside of

3:54

the promise instead of inside of the

3:56

promise callback. And that can be

3:58

handy if you want. You want to pass

4:01

those pretty much succeed and

4:03

cancel functions if

4:05

you want to pass them to something else. For

4:07

example, I have buttons on

4:09

an example somewhere where if

4:12

you press the done button, that

4:14

is resolved. But if you push the cancel button,

4:16

that is a reject. Often you can just wire

4:19

those up directly to an Ad Event listener and

4:22

you're up and running. So that's another way

4:24

you can cancel them. And then also in

4:26

Fetchland, we have this

4:28

idea called an Abort Controller. And

4:31

you create an Abort Controller

4:34

and that Abort Controller itself

4:36

has what's called a signal. You pass

4:38

that signal to a fetch request and

4:41

then you're able to control that fetch

4:43

request from wherever you have access to

4:45

the Abort Controller method. It's a little

4:47

bit more complex and simply just rejecting

4:50

because you do want to also cancel

4:52

the network request and that will take

4:54

care of all of that stuff for

4:56

you, as well as there's

4:58

a built-in signal for simply just doing a timeout.

5:01

Because if you want to set the timeout of

5:03

a fetch function, you don't

5:05

have to wrap it or anything. You simply

5:07

just pass the signal of abort signal.timeout 500

5:10

milliseconds and then nothing will reject if

5:12

there's no response back after five seconds.

5:16

Why would you reach for an abort signal? Because

5:18

that's not something I feel like I've ever had

5:20

to do. A good

5:22

example would be if you have

5:24

a type of head that is sending

5:26

off fetch requests. So you'll have a

5:29

search box, you start typing in cool and

5:31

then you stop for a second and it goes, I'm

5:34

gonna start searching for cool. So it sends a

5:36

fetch request off to your API and

5:38

as that fetch request is in flight, you

5:41

just type ify, F-I. Okay,

5:44

now you've sent off a second request

5:47

to the server for coolify.

5:49

Now you have two fetch requests

5:51

in flight and it is not

5:53

guaranteed that they will come back

5:55

in order That you've done

5:57

it. And Often developers don't realize this. Working

6:00

at a local database and on local

6:02

house and there's no latency at all

6:04

but you get into real world conditions

6:06

your database somewhere different the drax a

6:08

user there could be real world thing

6:10

so as you are typing if you

6:12

are firing off a second fetch requests

6:14

you need to make sure that you

6:16

up or any other. Requests. That

6:18

are currently still in flight, so that's where

6:20

you'd want to use an abort signal. Thank.

6:24

You thank you for that? Yes,

6:26

yeah. Fluid set about some of

6:28

these additional helpers for promises. You

6:31

may have seen some of these

6:33

like promise, dad. All words promised

6:36

at all except an array of

6:38

promises And is where it will

6:40

do. is it returns. Why

6:43

should the promise itself? Fulfills.

6:46

Once. The. Promises themselves

6:48

complete and A usually gives

6:50

you essentially an array of

6:52

the values that come back

6:54

from those promises. Now I

6:57

am curious west as I

6:59

know you know more about

7:01

this than I do. You

7:03

promise.all settled. What is the

7:05

difference between promise? All in

7:07

promise? All settled. So.

7:09

All was initially rolled out when

7:11

we got promises. And.

7:14

The downside to that is if one of

7:16

those values rejects know whole thing is is

7:18

over south from said I'll take that. I

7:20

like you said an array of promises at

7:23

wrap them up into one mega promise me

7:25

up and it waits for all of the

7:27

promises to be done. And if one of

7:29

I'm takes one second in one of them

7:32

takes ten seconds you're going to be way

7:34

the full ten seconds before you get all

7:36

of the dead rights. But if one of

7:38

those were to reject. You. Might

7:41

have to successful promises, but there's

7:43

no way to get that data

7:45

anymore because. It's is

7:47

rejected and immediately you go straight to

7:49

the cats. When you're you're chaining right?

7:51

known as kind of a pain. If

7:53

you do care about the successful ones

7:55

have a not out one that was

7:57

was failed rights like for example of

7:59

your. Uploading seven photos.

8:02

Are you might want to do

8:04

Promise.all. And upload all seven

8:06

concurrently on the same time. For.

8:09

Ref: one of them doesn't upload because

8:11

it's too large or a sarong. files

8:13

I personally like that's the other six

8:15

that may have been uploaded correctly or

8:18

are are still in process. They're.

8:20

All aboard at right and you're era.

8:22

You're outta luck. Know all Settled will

8:24

returns you an array of the results

8:27

regardless of if they were all successful

8:29

or not. Will give you an array

8:31

of to tax the data. Each item

8:33

in the array will be and will

8:36

have a status. Which is

8:38

fulfill the rejected which is. A

8:40

little annoyed to me that that's is called for.

8:43

Still the rejected sit in that say. Resolve.

8:45

Their rejected. Maybe. Knots

8:47

and then on successful ones. You'll get

8:49

a value property which has the data

8:51

that you're lucky for and then the

8:53

aired out ones. You'll get a reason

8:55

property which will have. Whatever.

8:57

is passed to the rejected method that

9:00

you have their so I would say.

9:02

I'm in. I'm in Unless you

9:04

are one Abort Everything. Abandoned.

9:06

All ship as soon as one of them

9:09

breaks. You probably want all settled in modern

9:11

is now and then. Promise that finally you

9:13

mention this last show of it being really

9:16

handy as if you want to do something

9:18

after it resolves or rejects like turn off

9:20

a loader. Then. You can

9:22

use finally. And. That or run

9:24

in either case. Now. There.

9:27

Is also I can confidently say I've

9:29

never used either of these. yeah I'm

9:31

I'm curious if you ever have he

9:33

he their this promise that any and

9:35

promise that race you want to guess

9:37

what those are more lascivious them yourself

9:39

and you have them Mrs I you

9:41

know it just looking at these I

9:43

would say. That. Any

9:46

resolves once any of the

9:48

promises have resolved. But.

9:54

Maybe Okay Here's when I'm in a guess.

9:56

This is this is just totally off the

9:58

wall guess for me. I'm gonna say

10:01

they both. Return.

10:03

Once the first promise resolves I

10:05

would imagine that maybe any also

10:07

resolve the other promises were race

10:09

stops trying to resolve the other

10:12

promises as close so they both

10:14

you're right in that they both

10:16

will resolve as soon as the

10:18

first promise is is uploaded. So

10:21

maybe have two different eighty eyes

10:23

and you're sending data to to

10:25

because you you want to have

10:27

like double back ups rights and

10:29

you only care. That.

10:32

Something has been sent to one

10:34

of them frames and both of

10:36

those will resolve as soon as

10:38

the first. One is

10:41

finished. The difference being

10:43

that. Promise. Dot

10:45

race or return the first

10:47

settled value. And

10:49

at a settled is a

10:52

reject or resolve were as

10:54

promised that any will return

10:56

the first fulfilled value. So.

10:59

Any his success only

11:01

race will return the

11:03

rejected or. For. Know can

11:05

resolve value sellers to and again

11:07

and I know like in in

11:09

what case or you're firing off.

11:12

Multiple. Promises? Maybe like. If

11:14

you had a promise that was

11:16

waiting for a click on multiple

11:18

buttons noom see you might have

11:20

like six promises that are waiting

11:22

for clicks on six different buttons.

11:25

You my only care. As

11:27

soon as somebody clicks one of those

11:29

buttons, and as soon as somebody close

11:31

one of those buttons, then you want

11:33

to continue on with the rest. So.

11:36

I put although like just you could

11:38

pass and multiple selectors to some like

11:40

that Us while I know that's a

11:42

contrived example that are China China twist

11:44

into work in here. Ah, if you're

11:47

out there and you're missing the this

11:49

insane guys I have the perfect use

11:51

case for this. Hit us up

11:53

on you tube! drop a comment in the

11:55

video below this video i want a

11:58

hero people are using race for specifically

12:00

because I have used any but I've

12:02

never used race before and either way

12:04

these aren't things I need to reach

12:06

for very often. Let's

12:08

talk about error handling within promises.

12:11

Now typically if you're chaining methods

12:13

on a promise you can always

12:15

add a .catch method that

12:17

takes a callback with the error that gets

12:19

returned there. So you've seen that where it

12:22

has a callback with an E or an

12:24

error then you can console

12:26

log the error you can throw it

12:28

to sentry you can do all kinds

12:31

of stuff with it to ensure that

12:33

your UI is responding accordingly to

12:35

whatever is happening with that .catch.

12:38

Now you can also use a

12:40

try catch statement to wrap your

12:42

await inside of when

12:44

you're going to await a promise. However

12:47

one thing that I learned from Wes

12:49

a little while ago is that you can mix

12:52

these approaches where you can

12:54

await a variable result but

12:56

still chain a .catch onto

12:58

that bad boy so that way you don't have

13:00

to wrap the whole thing inside of

13:02

a try catch. I don't know

13:04

why but try catch feels so obnoxious

13:06

to me it pop it like it and then

13:09

re-indents my code all by one it feels like

13:11

it takes up a lot of space that's

13:13

one of those ones where it's like I

13:15

will use the .catch method and I will

13:17

use await to get the

13:19

value out of a promise typically. One

13:23

kind of way that I've been writing a

13:25

lot of my promises lately is this idea

13:28

of writing a wrapper function around

13:30

your promises that will

13:32

internally run a try

13:34

catch and will return

13:37

from that function a

13:39

what's called a tuple and

13:41

a tuple is like an array

13:43

that has a known length and a

13:46

known type and back

13:48

in the day in Express.js

13:50

and No.js land the way that it

13:53

worked is your callbacks would often give

13:55

you the error and the data and

13:57

you would either have the error or

13:59

the data. data and that was really nice

14:01

because you could first check if there was an

14:03

error and if there's not

14:05

you can continue on with the actual

14:07

data and that's a little bit

14:09

tricky because you could

14:12

do try catch and then you

14:14

got to update variables outside of the scope

14:16

that's kind of annoying. You can use the

14:18

away and dot catch but if

14:20

you want the actual error on the next line

14:22

then again it's out of scope you don't have

14:24

access to it you gotta do some weird variable

14:27

things. So with this

14:29

idea of I call it collect

14:32

in my types of course we create a function

14:34

called collect and learn how to like use generics

14:36

to type something that is so abstract

14:39

but there's a really popular library out there

14:42

called await to JS and

14:44

this will just give you a function

14:46

that you can wrap your promises in and then it

14:48

will return to you an array

14:50

first item being the actual

14:52

error second item being the

14:55

actual data and that's really nice if you

14:57

need to first deal with an error before

15:00

you go on with

15:02

the rest of your thing most commonly being like

15:05

you try to save an item to a database you

15:08

get the result back you want to

15:10

first check hmm was there any errors saving that

15:12

item to the database if so

15:14

then render an error page

15:16

if not continue on with the rest of the

15:19

page maybe render out the user page. So

15:21

I've been a big fan of this approach. I

15:24

have two statements on this one. Yeah

15:26

we should take your collect and turn

15:28

it into a library and we can

15:30

call it collect call. That's good. That's

15:32

a good joke. Oh

15:34

that's great. Thank you. And

15:37

second I you

15:40

know just even saying this makes

15:42

me wonder why you know

15:44

dot catch or even

15:47

like it feels like the error should

15:49

be the first in my logical brain

15:52

when you're doing a promise like oh

15:54

if this fails take care of the

15:56

failure first then if it

15:58

didn't fail we know it succeeds like. Logically the

16:00

order of that makes way

16:02

too much sense I've never used a wait

16:04

to JS or any of this stuff before

16:07

but I like the way it reads when

16:09

you look at the code Yeah,

16:11

I was I always was a big fan

16:13

of this approach. I think it was I'm

16:18

trying to wonder like who popularized this in

16:20

node.js land. I think some of the even

16:22

the node API's that are callback based Were

16:25

like that it's been so long since

16:28

I've worked on it But yeah, it was always

16:30

give you the error first then the data and

16:32

that forces you to think okay Handle

16:34

the bad case first and then you have your

16:36

your happy path gotta have your happy

16:39

path. So Yeah, that's I

16:41

have a little YouTube video. I'll link up here

16:44

detailing the different a

16:46

sink away error handling strategies because Not

16:50

one is better than the other I use all of

16:52

them. Sometimes I try catch sometimes the catch is good

16:55

Often a mix and match is really good. And

16:57

then if I'm doing it specifically when

16:59

I do a lot of like node.js Database

17:01

work I'll reach for the collect

17:04

or a wait to JS Implementation.

17:07

Yeah. Yeah, it

17:09

is interesting because you like you said like

17:12

you do it different ways to me It's

17:14

one of those as a

17:16

feeling things because you can typically write most

17:18

of the stuff you're gonna do with any

17:20

of these approaches and I

17:22

think over time you just kind of get a feeling

17:25

for which way you like to do what and then

17:27

that's typically How it

17:29

feels for me. I have a

17:31

really good promise dot race example So

17:33

often when I don't know how people

17:36

use API's I'll just go

17:38

on get up search and search for that

17:40

API and yeah I do that Tim scroll

17:42

through 15 20 different code

17:44

examples Like what are people actually using this for

17:46

and you know what? This is such a good

17:48

example of what is used for is that if

17:52

you want to add a timeout? To

17:54

something that has a promise, but that

17:57

promise Doesn't have

17:59

the option to pass it in like you're

18:01

using somebody else's API. They don't allow

18:04

you to pass in a timeout, right?

18:06

Or you have your own promise based function, but

18:09

then you have to re implement

18:11

the timeout functionality in every function.

18:14

And you know, you have to add a timer

18:16

to it. And that's annoying. That's one of the

18:18

nice things about fetch where it's built in, but

18:20

not everything is a fetch. So promise.race, what

18:24

you can do is you can say, uh, const

18:26

result equals await promise.race,

18:29

pass it your original promise function and pass

18:33

it a like a timeout function that

18:35

will throw. And then

18:37

that's beautiful because it makes sense either, or,

18:39

or not even throw. You could just resolve

18:42

after one second. And then

18:44

if, if the result is empty, then it timed

18:46

out. And if the result is there, then, then

18:48

it worked. Love that. Hey,

18:50

love that. Yeah. I

18:53

learned a thing or two. Uh, last thing

18:55

we have here is the capital P promise

18:58

in JavaScript has two static methods

19:00

on it. So dot reject and

19:02

dot resolve. And I've always wondered like,

19:05

why are those there? You know, like

19:08

what are those for? And I realized

19:11

I had used them a couple of times is if

19:13

you are returning values from

19:15

a function that may not be a promise, but

19:18

you want to still maintain the whole promise API

19:21

because everything else you're

19:23

working with is a promise. So for example, you

19:26

might have a cache API that it

19:29

either fetches some data and returns to you

19:32

or it would just pull it out from the cache and return it to you. So

19:37

by returning promise.resolve with some data, it

19:42

just turns your static data like

19:44

promise.resolve 42. It turns it into

19:46

a promise that immediately resolves to 42. And

19:50

that's great if you're trying to like keep

19:52

the chaining or your, your,

19:54

your passing something to a function that expects

19:56

a promise. and

20:00

not just a straight up value. So

20:02

I think a sink await kind of did away with

20:04

the need for most of this stuff because if you

20:07

have an async function that returns 42, that's the same thing.

20:12

But if you need to

20:14

turn a function that

20:16

returns a value into a function that

20:18

returns a promise of a value, that's

20:21

where you use reject and resolve methods. The

20:24

static ones on P promise. Hmm.

20:29

That's what are we out here? 23

20:31

minutes? Yeah, that's enough for a part

20:34

two. Hopefully you learned a thing or two

20:36

on next Monday. We have the third installment

20:38

of the series coming out where we're going

20:40

to talk a little bit more about queuing

20:43

and concurrency and running promises in

20:45

series and a whole bunch of

20:47

libraries that are helpful for working

20:49

with this type of stuff. Take

20:53

all right. Take it later. Peace.

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