Coding

Callbacks vs Promises vs RxJs Observables vs async/ await

  • 00:00:01 welcome to this video great to have you
  • 00:00:04 on board
  • 00:00:04 my name is Maximilian and in this video
  • 00:00:06 I want to dive into a super important
  • 00:00:09 topic in JavaScript development handling
  • 00:00:12 asynchronous operations with callbacks
  • 00:00:14 promises rxjs or async await when should
  • 00:00:20 we use which tool and how do they
  • 00:00:21 actually differ we'll take a closer look
  • 00:00:24 at these questions in this video
  • 00:00:29 so handling asynchronous operations is a
  • 00:00:33 super important task in JavaScript
  • 00:00:35 you're probably going to write or treat
  • 00:00:37 any application which doesn't use some
  • 00:00:40 asynchronous operation now JavaScript
  • 00:00:42 offers you different ways of handling
  • 00:00:44 asynchronous operations because by
  • 00:00:47 default JavaScript of course is
  • 00:00:48 synchronous executes one line of code
  • 00:00:50 after the other and therefore you need
  • 00:00:53 certain approaches or tools to handle
  • 00:00:55 these asynchronous cases I actually did
  • 00:00:58 a write an article about that too so if
  • 00:01:00 you're more like a reading guy or you
  • 00:01:02 want to read after watching this video
  • 00:01:04 check out this article where I will dive
  • 00:01:07 into the main or the major approaches
  • 00:01:10 offered by JavaScript and outline how
  • 00:01:12 they work and how they differ and when
  • 00:01:14 you might want to choose which of course
  • 00:01:15 I'm also going to take a look at this
  • 00:01:17 question in this article so let's do
  • 00:01:19 this right now for that I created four
  • 00:01:22 examples you can find links in the video
  • 00:01:24 description and I want to start with
  • 00:01:25 callbacks the whole list or simplest way
  • 00:01:30 of handling asynchronous code in
  • 00:01:32 JavaScript now here on the left you see
  • 00:01:34 my JavaScript code on the right you see
  • 00:01:36 a button let's click the button first if
  • 00:01:38 you wanted s click 'add its first
  • 00:01:40 checking authentication fetching a user
  • 00:01:42 and then displaying the user the user
  • 00:01:44 named max my name okay
  • 00:01:46 so what's happening here well in the
  • 00:01:48 code up first of all get access to the
  • 00:01:49 button and then to the div where I want
  • 00:01:51 to render that username nothing
  • 00:01:54 asynchronous thus far then I have three
  • 00:01:57 functions here I'm using arrow functions
  • 00:02:00 the es6 feature but in the end it's just
  • 00:02:02 functions the first one is just a helper
  • 00:02:04 function which will render the text 1
  • 00:02:06 the user name basically could use it for
  • 00:02:08 any text once I got it so here I'm just
  • 00:02:10 accessing text content of the day if I
  • 00:02:12 fetched and output some text then check
  • 00:02:15 off is just a faking asynchronous
  • 00:02:18 function where I use a timeout over Q
  • 00:02:21 seconds q then do something to which
  • 00:02:24 I'll come back and I also call set text
  • 00:02:27 to display checking off here instead of
  • 00:02:30 the username once I am checking the off
  • 00:02:32 now of course in a real application you
  • 00:02:35 would probably reach out to a server
  • 00:02:37 here for example to verify if some token
  • 00:02:40 is valid if user is logged in and here
  • 00:02:42 I'm just faking
  • 00:02:43 that we have to wait for the actual
  • 00:02:45 response whoever it is true or false I'm
  • 00:02:48 doing this what set at the time out as
  • 00:02:49 mentioned the same for fetch user here
  • 00:02:51 I'm always updating the text and then I
  • 00:02:54 use a timeout
  • 00:02:55 to fake the fetching of a user now you
  • 00:02:58 probably already see this CB failure
  • 00:03:01 which I call inside the timeout so once
  • 00:03:04 the timer finished and that is the
  • 00:03:06 argument these arrow functions receive
  • 00:03:09 here so CV is just the argument passed
  • 00:03:11 to the function that leads us to the
  • 00:03:14 question what is the argument and who's
  • 00:03:17 calling these functions the argument
  • 00:03:21 obviously is a function itself because
  • 00:03:23 we execute it like a function passing an
  • 00:03:25 argument to the function then this case
  • 00:03:27 we're executing CB and pass through here
  • 00:03:30 we execute CB and pass a JavaScript
  • 00:03:32 object and the one calling CB is inside
  • 00:03:36 here the event listener on the button
  • 00:03:38 here I call check off then I pass a
  • 00:03:43 function that's just another arrow
  • 00:03:45 function here to check off that's super
  • 00:03:48 important I'm passing an anonymous
  • 00:03:50 function here Q check off and remember
  • 00:03:54 check off did require a function C be
  • 00:03:58 called here you can of course rename the
  • 00:04:00 argument here so I'm passing a function
  • 00:04:03 to check off which check off will
  • 00:04:06 execute once the timer completed and it
  • 00:04:09 will then pass true Q that function is
  • 00:04:12 got as an argument
  • 00:04:14 so basically keep that function of the
  • 00:04:19 argument of that anonymous function will
  • 00:04:21 be true in the end because I pass
  • 00:04:23 through to the function pass to check
  • 00:04:25 off that this anonymous function so this
  • 00:04:28 anonymous function gets called whenever
  • 00:04:31 this timer and check off is done and
  • 00:04:34 then we pass true as an argument to that
  • 00:04:37 function so off will be true and the
  • 00:04:40 next time I do check that and this is
  • 00:04:43 already asynchronous here this code
  • 00:04:45 inside this anonymous function will only
  • 00:04:48 run once the timer completed because
  • 00:04:51 what we do here is we tell JavaScript
  • 00:04:54 hey please don't stop X
  • 00:04:57 fusion it wouldn't do that anyways but
  • 00:04:59 be aware that whenever the timer is done
  • 00:05:02 you should execute this function your
  • 00:05:05 dis anonymous function which then in
  • 00:05:07 turn executes call back true that is
  • 00:05:11 what we tell JavaScript be aware that
  • 00:05:13 you have to do this in the future once
  • 00:05:16 the timer is done so this code here only
  • 00:05:19 runs once it is done once the timer
  • 00:05:22 completed then we checked off the value
  • 00:05:25 the timer gave us and then we execute
  • 00:05:27 another function fetch user so that's
  • 00:05:31 this function here that's user and it
  • 00:05:33 works in the same way we passed an
  • 00:05:36 anonymous function to fetch user this
  • 00:05:38 error function here where we expect to
  • 00:05:41 get a user then and this anonymous
  • 00:05:44 function is now executed inside the
  • 00:05:46 timer of fetch user after two seconds we
  • 00:05:49 execute what fetch user received our
  • 00:05:52 anonymous function we execute it and
  • 00:05:55 pass an object to that function so a
  • 00:05:58 user here will be that JavaScript object
  • 00:06:02 well and then we simply call set text in
  • 00:06:05 there so check off is executed and the
  • 00:06:08 anonymous function for check off will
  • 00:06:10 run after two seconds
  • 00:06:11 so after this timer of check off and
  • 00:06:14 then inside of that code which runs
  • 00:06:16 after two seconds we reach out to
  • 00:06:18 another function which uses a timer so
  • 00:06:21 that after a total of 4 seconds we will
  • 00:06:24 run this code two seconds from check off
  • 00:06:26 in two seconds from inside here from
  • 00:06:29 that user timer and this is what happens
  • 00:06:31 here we click fetch user checking off
  • 00:06:33 for two seconds fetching the user for
  • 00:06:35 two seconds and then seeing the user
  • 00:06:37 these are callbacks and on the first
  • 00:06:41 look there's nothing wrong with that
  • 00:06:43 right we use callbacks looks like a good
  • 00:06:45 solution to that we tell JavaScript to
  • 00:06:48 do something at a later point of time so
  • 00:06:50 that it can continue executing the rest
  • 00:06:52 of the code and then just execute dev
  • 00:06:55 coded remembered once it needs to be
  • 00:06:57 executed the issue is something we can
  • 00:07:00 already see here we're nesting all these
  • 00:07:03 callbacks imagine we would not output
  • 00:07:06 the text in that fetch user but then do
  • 00:07:09 something else
  • 00:07:10 call some sir
  • 00:07:11 that function which transforms the user
  • 00:07:13 then we would have transformed user this
  • 00:07:15 function doesn't exist here but we could
  • 00:07:17 have that and there we would pass not
  • 00:07:19 recall that function where we get the
  • 00:07:22 transformed user back which you can then
  • 00:07:25 handle in there so handle transformed
  • 00:07:28 user and you can already see where this
  • 00:07:31 is leading to you we got a lot of
  • 00:07:33 nesting going on and this is actually
  • 00:07:35 called callback hell because you add
  • 00:07:39 more and more callbacks and it gets
  • 00:07:41 super hard to mention to understand
  • 00:07:43 error handling becomes a pain because if
  • 00:07:46 you handle an error inside a callback
  • 00:07:48 you probably want to call another
  • 00:07:50 callback and that's no fun
  • 00:07:53 hence Java Script gave us a solution to
  • 00:07:56 that with es6 or already earlier if you
  • 00:07:59 used some third-party libraries promises
  • 00:08:02 the general setup here is the same I
  • 00:08:04 still fetch get access to the button and
  • 00:08:07 to the depth and as you can see if I
  • 00:08:09 click this it works the same as before
  • 00:08:11 checking all fetching user outputting
  • 00:08:13 the username but the code inside check
  • 00:08:16 off and fetch user changed here I'm not
  • 00:08:20 calling some callback anymore you can
  • 00:08:22 see these functions don't receive an
  • 00:08:24 argument anymore
  • 00:08:25 instead I'm returning a new promise and
  • 00:08:29 promises are a construct a class
  • 00:08:32 introduced by es6 promises as their name
  • 00:08:36 suggests our classes which promise a
  • 00:08:39 certain value in the future so they're
  • 00:08:42 also a tool for handling asynchronous
  • 00:08:43 code in this case here the promise or
  • 00:08:48 always a promise if you create one on
  • 00:08:50 your own and as a side note oftentimes
  • 00:08:53 you don't create promises on your own
  • 00:08:55 but you use some third-party library
  • 00:08:57 like axioms for making HTTP requests
  • 00:08:59 which will automatically give you a
  • 00:09:01 promise but here we're creating it on
  • 00:09:03 our own we created on your own recalling
  • 00:09:06 new promise and to the promise
  • 00:09:08 constructor I passed an anonymous
  • 00:09:10 function which gets two arguments result
  • 00:09:12 and reject these are actual functions
  • 00:09:14 you can execute inside that anonymous
  • 00:09:17 function here and here and then is again
  • 00:09:19 creating a counter a timer inside my
  • 00:09:23 promise anonymous function
  • 00:09:25 and after the two seconds I call the
  • 00:09:26 result function here which will
  • 00:09:29 basically inform JavaScript this promise
  • 00:09:31 is done we got a value and this is
  • 00:09:34 something you need to do in the promise
  • 00:09:36 man because you do promise a value you
  • 00:09:38 could also call reject to throw an error
  • 00:09:40 but here I'm just using result and then
  • 00:09:43 we result true at the same for the user
  • 00:09:46 here I resolve my JavaScript object
  • 00:09:50 now first look you might say well that
  • 00:09:52 doesn't look that much easier than for
  • 00:09:54 cold X now but again keep in mind
  • 00:09:56 oftentimes you're not the one creating
  • 00:09:59 these promises oftentimes you will use
  • 00:10:01 some library which already gives you
  • 00:10:02 promises the interesting part comes if
  • 00:10:04 we have a look at how we can use
  • 00:10:06 promises down here this is much cleaner
  • 00:10:10 code we listen to the click and then
  • 00:10:13 inside this click handler we call check
  • 00:10:16 off and then we don't pass any function
  • 00:10:19 to check off which gets nested but we
  • 00:10:22 simply call then change to the check off
  • 00:10:25 call now then takes an anonymous
  • 00:10:29 function where we handle this value we
  • 00:10:33 get back from the promise so true in the
  • 00:10:36 case of check off that gets stored here
  • 00:10:39 that gets automatically passed as an
  • 00:10:41 argument and then I simply return a new
  • 00:10:45 function call return fetch user calling
  • 00:10:48 that second function which all returns a
  • 00:10:50 promise keep that in mind now here we're
  • 00:10:53 returning this and in the past we would
  • 00:10:55 then kind of like ever use a call back
  • 00:10:58 in there or with promises you could
  • 00:11:00 think you've now called then their cue
  • 00:11:02 but the cool thing is if you return a
  • 00:11:04 promise inside of then block you can
  • 00:11:06 simply chain another event block after
  • 00:11:08 the first one so you never have this
  • 00:11:11 deep nesting of callbacks or anything
  • 00:11:14 like that you simply have then after
  • 00:11:16 then after then until you're done
  • 00:11:18 like here that's the last then block we
  • 00:11:20 then get a user which we output so if
  • 00:11:23 you got deeper layers of nesting
  • 00:11:26 promises are great because you never get
  • 00:11:28 the same behavior there you just have
  • 00:11:30 then after then after then and it's also
  • 00:11:32 easier to handle errors you could read
  • 00:11:35 more about that in the article I
  • 00:11:36 mentioned at the beginning of the video
  • 00:11:38 so that promises already a great tool do
  • 00:11:42 we need more well there is another
  • 00:11:44 construct named rxjs which gives us
  • 00:11:48 observables
  • 00:11:49 now our XJS observables are not a native
  • 00:11:52 javascript features like promises are
  • 00:11:54 but they are made available through a
  • 00:11:57 third-party library rxjs is the name of
  • 00:12:00 the library same code as before here
  • 00:12:02 when it comes to getting access to the
  • 00:12:04 Dom but then check off and fetch user do
  • 00:12:07 something else something different they
  • 00:12:09 return and observable basically it looks
  • 00:12:12 at bit similar to the promise we create
  • 00:12:15 something here and then we pass a
  • 00:12:17 function to what we created and in there
  • 00:12:19 we call set timeout and object to
  • 00:12:20 seconds we call in this case the
  • 00:12:22 observer and the next function but
  • 00:12:24 that's kind of like resolve for the
  • 00:12:26 promise we basically emit a new value a
  • 00:12:30 core distinction between promises
  • 00:12:33 observables is that promises handle one
  • 00:12:36 value you send the HTTP request you get
  • 00:12:39 a response you resolve your promise
  • 00:12:41 you're done for observable that's
  • 00:12:44 different
  • 00:12:45 you can handle streams of data there you
  • 00:12:48 can wrap and observable around a click
  • 00:12:51 listener you listen to every new click
  • 00:12:53 and emit a new value on every new click
  • 00:12:56 that's not possible like this with
  • 00:12:58 promises here again we're just setting
  • 00:13:01 up our simple observables and then down
  • 00:13:03 there you see this wrapping around an
  • 00:13:05 event in the past we used add event
  • 00:13:08 listener on the button here I'm using an
  • 00:13:11 observable method to create a new
  • 00:13:13 observable from an event an event on the
  • 00:13:16 button the click event and then here
  • 00:13:19 we're using something the rxjs library
  • 00:13:22 offers so called operators and there are
  • 00:13:25 loads of operators
  • 00:13:26 made available I actually do have rxjs
  • 00:13:30 series on this channel in case you want
  • 00:13:32 to dive deeper these operators are great
  • 00:13:34 though because you simply chain them
  • 00:13:36 after each other so likely then calls
  • 00:13:40 for a promise here in this case switch
  • 00:13:43 map basically handles the first
  • 00:13:47 asynchronous value which comes from this
  • 00:13:49 click event so we get to click event
  • 00:13:51 and let me call check off and that's
  • 00:13:54 just a short es6 arrow function keep in
  • 00:13:57 mind that this in the end returns check
  • 00:13:59 off that's important to know so we
  • 00:14:01 return whatever check off gives us and
  • 00:14:03 check off just gives us an average
  • 00:14:06 servable we call another switch map
  • 00:14:09 which will just take the last observable
  • 00:14:11 so the one return if I check off it Maps
  • 00:14:14 it into a new one in this case the one
  • 00:14:16 we get from fetch user so we use the
  • 00:14:19 value from check off and return a new
  • 00:14:21 observable and in the end that that is
  • 00:14:23 something you have to do in every
  • 00:14:24 observable you have to subscribe once
  • 00:14:27 your chain ends so what you want to do
  • 00:14:29 after you went through all your
  • 00:14:30 observables in this case we subscribe we
  • 00:14:33 know that we will get a user in the end
  • 00:14:34 that's just what scheduled gets returned
  • 00:14:37 back that user and we can output it here
  • 00:14:39 and hence if we click this we get the
  • 00:14:41 same behavior as before but now using
  • 00:14:43 rxjs and rxjs can be a little bit more
  • 00:14:49 complicated to learn although due to the
  • 00:14:51 many operators that offers but being
  • 00:14:54 able to handle streams of data again not
  • 00:14:57 that easy with promises and having all
  • 00:15:00 these operators which can be complicated
  • 00:15:03 I'll give you that but which also offer
  • 00:15:05 use so much possibilities and
  • 00:15:08 opportunities to work with your data
  • 00:15:10 streams these are two arguments really
  • 00:15:14 in strong favor of rxjs and personally I
  • 00:15:18 can only recommend trying out rxjs
  • 00:15:21 observables and working with them they
  • 00:15:24 can really enhance your project quite a
  • 00:15:27 lot on the other hand it's of course not
  • 00:15:29 the perfect solution for every project
  • 00:15:31 if you guys very simple asynchronous
  • 00:15:33 operations you don't need to handle data
  • 00:15:36 streams and you don't need all these
  • 00:15:37 operators it doesn't add that much value
  • 00:15:41 to your app to bring in the rxjs library
  • 00:15:44 which of course will also increase your
  • 00:15:46 final bundle size that's something you
  • 00:15:48 have to keep in mind it's not a native
  • 00:15:50 JavaScript feature so it will add to
  • 00:15:52 your bundle size but if you are working
  • 00:15:54 with data streams or if you do will see
  • 00:15:57 that these operators add some benefits
  • 00:15:59 definitely check out observables so
  • 00:16:02 observables are awesome and promises are
  • 00:16:05 good alternative what else do we have
  • 00:16:08 then I think a wait that's a new feature
  • 00:16:12 coming with JavaScript es8 still you can
  • 00:16:17 already use it with some transpilers
  • 00:16:19 like babel for example and adding some
  • 00:16:22 polyfills probably here we get the same
  • 00:16:24 starting set up and then we return
  • 00:16:26 promises just like in the promises
  • 00:16:29 example the code up here for check off
  • 00:16:32 and fetch user is exactly identical
  • 00:16:34 because async await just uses promises
  • 00:16:38 behind the scenes that's super port to
  • 00:16:40 keep in mind async await uses promises
  • 00:16:42 it's not a yet another alternative it
  • 00:16:45 uses promises it gives you a different
  • 00:16:48 way of handling these promises once they
  • 00:16:50 resolve or reject though let's scroll
  • 00:16:53 down here we have our event listener and
  • 00:16:56 if you check this code
  • 00:16:58 it looks very synchronous doesn't it we
  • 00:17:01 create a constant we initialize a user
  • 00:17:04 variable with the if check where we set
  • 00:17:06 the user variable and then we set text
  • 00:17:09 this looks like synchronous code one
  • 00:17:12 command running after the other there is
  • 00:17:14 no nesting with callbacks no then calls
  • 00:17:17 and no subscribe calls from rxjs there
  • 00:17:22 are cue important keywords though async
  • 00:17:25 and a weight async has to go in front of
  • 00:17:31 your function definition so here we're
  • 00:17:34 defining and passing an asynchronous
  • 00:17:36 function excuse me an anonymous function
  • 00:17:39 just a normal anonymous arrow function
  • 00:17:42 and we turn it into an asynchronous
  • 00:17:45 function by adding the async keyword in
  • 00:17:49 front of it now to JavaScript this will
  • 00:17:52 signal that everything inside that
  • 00:17:55 function may use the await keyword to
  • 00:17:59 pause the JavaScript execution you could
  • 00:18:02 say that is what await does here we
  • 00:18:07 assign a constant and we tell JavaScript
  • 00:18:09 the value of the constant should be what
  • 00:18:12 to check off resolves to what the
  • 00:18:15 promised return fight check off resolves
  • 00:18:18 to
  • 00:18:18 keep in mind I said it two seconds ago
  • 00:18:21 async/await
  • 00:18:22 uses promises and only works with
  • 00:18:25 promises check all pro turns a promise
  • 00:18:28 and we can then wait for this promise to
  • 00:18:30 resolve and JavaScript will basically
  • 00:18:33 wait or behind the scenes use then again
  • 00:18:36 wait for check off to to resolve and
  • 00:18:40 then store it here and only then it will
  • 00:18:43 move on and execute the next code line
  • 00:18:45 that is why you can only use it in
  • 00:18:48 especially marked functions because the
  • 00:18:50 default behavior of JavaScript is a
  • 00:18:52 different one each line gets executed
  • 00:18:54 after the first one and it doesn't wait
  • 00:18:56 for some async operation to finish now
  • 00:18:59 here in such async functions it kind of
  • 00:19:02 does and we signal it for to wait with a
  • 00:19:05 wait the same here for fetch user which
  • 00:19:08 held JavaScript don't execute this line
  • 00:19:11 set text before this operation here is
  • 00:19:14 done and we stores the resolved user in
  • 00:19:17 the user variable here that is why if I
  • 00:19:20 click this button we see the same
  • 00:19:22 behavior as before but now without
  • 00:19:24 calling then or using coal bags or
  • 00:19:27 subscribe a thing away therefore it's a
  • 00:19:30 great tool to write easy-to-understand
  • 00:19:32 code which looks like synchronous code
  • 00:19:35 and therefore definitely a tool you
  • 00:19:38 should keep in mind and you should use
  • 00:19:39 when working with promises and when
  • 00:19:41 working with chains of promises where
  • 00:19:44 you have a lot of then blocks after each
  • 00:19:46 other maybe because you can write very
  • 00:19:48 clean code with async await just be
  • 00:19:50 aware it's always the combination of
  • 00:19:52 async and a weight you can only wait in
  • 00:19:55 async functions now again check out this
  • 00:19:58 article I referenced at the start of the
  • 00:20:00 video if you want to learn more I hope
  • 00:20:02 this video gave you a good overview over
  • 00:20:05 these four tools for handling
  • 00:20:08 asynchronous operations in the video
  • 00:20:10 description you can find more links with
  • 00:20:12 more resources to dive into these
  • 00:20:14 different tools and you learn more about
  • 00:20:16 that if you want to do that I hope you
  • 00:20:19 enjoyed the video see you in future
  • 00:20:20 videos hopefully bye