Back to the basics

Rate this content
Bookmark

“You’ll never believe where objects come from in JavaScript.”


“These 10 languages are worse than JavaScript in asynchronous programming.”


Let’s explore some aspects of JavaScript that you might take for granted in the clickbaitest nodecongress.com workshop.


To attend this workshop you only need to be able to write and run NodeJS code on your computer. Both junior and senior developers are welcome.


Objects are from Mars, functions are from Venus


Let’s deep-dive into the ins and outs of objects and then zoom out to see modules from a different perspective. How many ways are there to create objects? Are they all that useful? When should you consider using them?


If you’re now thinking “who cares?“, then this workshop is probably for you.


Asynchronous JavaScript: the good? parts


Let’s have an honest conversation.


I mean… why, oh why, do we need to bear with all this BS? My guess is that it depends on perspective too. Let’s first assume a hard truth about it: it could be worse… then maybe we can start seeing the not-so-bad-even-great features of JavaScript regarding non-blocking programs.

128 min
15 Feb, 2022

Comments

Sign in or register to post your comment.

Video Summary and Transcription

This workshop covers basic principles and patterns in software development and engineering. It explores topics such as objects, functions, prototype chains, classes, modules, and asynchronous programming in JavaScript. The workshop emphasizes the importance of understanding context, encapsulation, and the use of promises for managing asynchronous behavior. It also discusses the differences between synchronous and asynchronous code execution and provides insights into the design patterns and best practices for writing efficient and maintainable code.

Available in Español

1. Introduction to Workshop

Short description:

Thanks for joining this workshop on basic principles and patterns. I believe they are the best investment in your formation. Today, we'll focus on two topics: objects and asynchronous behavior of Node.js.

So I think we can start now, again, my name is Guillermo I'm your host today. Thanks for joining this workshop and a special thanks for coming because I know this is not the flashiest topic out there. Like basic principles and patterns is not a fancy framework that everybody is using or things like that.

So, yeah, good for you, too, I guess. Yeah, there's going to be a recording of this session and I think that the organization will put it on where you can access it. Yeah. There you go. Cool.

So, again, my name is Guillermo. I'm a software developer probably like most of you. I work at the company called DnSimple as a staff software engineer. I normally work on Ruby. But I also work a lot on JavaScript and in the past I've also worked on Java code bases, too. At DnSimple, we are a small team. And, by the way, we are looking for people to join us. So, be sure to check out our jobs page. If you're on the market for a job, we'll be happy to hear about you.

So, this workshop the basics, right? And I really meant it when I put that title. Because when I give talks and trainings like this one, I always try to bring it down to basic principles and patterns. Because that's what I honestly believe it's the best investment anyone can make in their formation. Because you know, frameworks and libraries tend to change so much, they're really volatile, whereas basic principles and patterns are things that have been around for a long, long time, and have been proven to be valuable and useful through time. So there you go. That's basically how I try to think about it. And also, in a two hours remote workshop like this one, there's not so not a lot of room to to talk about a lot of things and go into a lot of detail. So that's why I wanted to focus just on two topics, one objects and two asynchronous behavior of Node.js because I think those are topics that most of the people I know struggle with and these are also things that we take for granted without really having too much time to think about them and reason about them and get really into knowing how they work.

2. Understanding Objects and Values in JavaScript

Short description:

No practical notes will be given. We will focus on code for the next two hours. Objects are collections of key-value pairs in JavaScript. Values can be anything you put to the right of an equals sign. Let's look at an example with the variable foo and the property A. We can access the A property using dot notation or square bracket notation. Both will return the value 44.

So let's cut to the chase. Someone asking if practical notes are going to be given? No, I'm sorry, I haven't prepared any practical notes for you. It's just about dealing with the code that we are going to see for the next two hours and of course the repo will be there, it's public and you can do what you want with it afterwards. So, again, these are nuanced topics that require a lot of time to get into details etcetera.

And what I'm going to say then during the next couple of hours, you need to understand that these are only mental models, heuristics, ways to think about things, not canonical descriptions of how things are in the language, okay? So, let's start with the objects. So, the first topic was objects are from Mars, functions are from Venus. This was kind of a silly joke. But, really, what is an object, and why should I care? That's just the question I will try to answer. And the thing is that the way I think about objects is as if they were values that have this shape of a collection of key value pairs. So, in JavaScript, keys of those objects are called properties. And values, a value, right? So, oh. Okay. I'm going to enable this. I don't know if it's going to work. So, live transcription. There you go. It works. Okay. Let's continue.

So, what is a value, right? Whatever you can put to the right of an equals sign, that's a value in JavaScript. And you will find that almost anything is a value. You can actually put anything you want to the right of an equals sign. I was really trying really hard to think of something that was not a value, but I didn't find anything. So, let's jump to the first I have for you, we have a couple of folders. One is objects and the other one is called a sink. So, let's take the part1.js file. And you will find three lines here. And this is showcasing how an object can be thought of as a collection of key value pairs. Right? In the first line here we are creating a variable called foo. And to the right of the equal sign, I mean this part of the equal sign, we have curly brace and then an A which is the properties name. Then a colon and then 44 which is the value that I'm assigning to call A. This is an object, right there. And yeah. It has only one property with just the value. And I know that we are kind of talking about very simple things, but this we will grow on top of everything we introduce. Right? So we need to establish like the basics, right. This is what we're doing right now. And the way that we can reference the A property on foo is by using the dot notation or the square bracket notation. And you have an example of that in the following lines. The first line here, console.log, foo.A, this is a dot notation. And the next line is using the square brackets notation, where you have foo, square bracket. Oops, sorry, moving that. Square bracket. And then the property name as a string. And that will get you 44 in both cases. So, the way that code sandbox works is you've got to the bottom right, you have a section with terminal tab, console tab, and problems tab. And you have a very small plus sign on the right edge that you can click. And that should get you a new terminal. And I'm going to enable that for all of you that are following me here. So, if you create a terminal, this is basically a prompt, where you can run things.

3. Objects and Functions in JavaScript

Short description:

Objects are collections of key value pairs. Functions can be assigned as values of a property. Calling a function by its name and executing it with parentheses is different from calling a function as a property of an object. The code execution results in the expected output.

And I'm not sure if you are seeing this, but I'm writing node objects slash part one. Oh, I have my keyboard in Spanish. So, let's change that. Objects, and then I hit return. And there you go. Oh, by the way, I gave you edit permissions to change that, so please, try to not change things. If you accidentally change something, just give me a heads up in the chat, and I will restore it. But we are basically sharing the same files, so please don't change things. Because otherwise, you won't be able to create the terminal to the right. So, again, if you open a terminal, and we are going to use this a lot during the workshop, you can run this file that we are editing here, the part one.js file. So, can anyone confirm that they were able to open a terminal and run this in their code sandbox session, please, for me?

Okay. A couple of confirms more, please, so that I can move on. I created a terminal, but, actually, I'm not able to write any code, so I cannot confirm. But I see a screen, so for me a good start, and maybe later I will fix it. During some rehearsals, some of the people that tried this had the same problem, and they kind of refreshed the screen, and it started working for them. So maybe you can try that, too. But yeah, if you are following me on the screen, and you are seeing what I did here, you will see that I run the script, and then I got the two console local lines from lines three and four, and I got what we expected, right? We got Foo.a equals 44, and Foo sqrt bracket of a equals 44. So refreshing works. Awesome. This is working. I wasn't sure that maybe with 60 people, I don't know, it would stop working or something, but I'm happy to see that. Yeah, and I confirm that refresh is fixing, and I was able to create again terminal. It's working. Thank you. Thank you. Awesome. This works. Okay, cool. So let's continue, right? I'm going to make this bigger for us. Cool. So we've seen that objects are collections of key value pairs. Keys are called properties, and anything, almost anything, can be a value. Next, what I'm going to do is I'm going to remove this comment here so that now the file will execute until line 21, in this case. Cool. So, what we're seeing here is that functions are also values too. Like, they can be assigned as values of a property. So, to show that, I'm creating here a full function that we'll create some constant and some console log call here. And then I'm creating a bar object that has a B property, and then this bar object has a full property. And its value is the function that I created on line 8. Do you see that? That it's referencing this function here. And now, what I'm doing in lines 18 and 19 is basically calling what is the same function in two different ways. And this is important that we understand how different these calling the function in isolation. Like I'm doing here. I'm just, you know, taking the name of the function. And using some parentheses here to execute that function. This is different than doing this where I run the full function as a property of the bar object. What is being held or stored in the full property. Right? So let's run this in the terminal, node objects slash part 2, oh, no, no, part 1, sorry. And then what we got, I'm going to copy this in the chart. So, what we got is the first two lines from the previous experiment and then two new lines.

4. Understanding Function Context in JavaScript

Short description:

The console log prints values A, B, and C. The first console log at line 18 prints undefined, while the second console log at line 19 prints 33. Functions have a context of execution, represented by the 'this' keyword. The context can differ depending on how the function is called. Different methods like call, apply, and bind can be used to set the context. When calling a function as a property of an object, 'this' refers to the object itself.

And here we need to take a look at what the console log is doing here. The console log will print some value called A, which we are defining in line 6. Then it's printing out this dot B, whatever that is. We haven't explained what this is, really, but it's doing that for now. And then C, which is declaring the same function. The value of A and C, I think it's easy for you to link, you know, that this is going to be 1 and this is going to be C. It's probably easy to see. It's more difficult to see what is going to be this here.

The first console log that corresponds to line 18 is printing out undefined. And the second console log, corresponding to line 19, is printing out 33. And this is because this, for some reason, when I call the function as a property of the bar object, it's understanding that this is actually the bar object. So when it's referencing the b property on this, it's going to take this one here, b equals 33. On the other hand, when I run the function in isolation, the function doesn't know about any of this dot B, and that's why I'm getting undefined.

The bottom line here is that functions have what we call a context of execution, and that context is basically the value of this, which is a special name. When you call this in a function, it can mean different things, depending on the context of execution of that function. When you call the function in isolation, like I did here, this will correspond to the global object. And when you call the function as a property of an object, like I did here, this will become the object itself. And we can prove that by declaring here a value for B. And now that I saved, if I run the script again, oh, it's, well, nevermind. Don't worry. Let's run the next example to see the context setting here. Also, another form of setting the context, bind, but there you go. Yeah, there are different ways to set the context using the different methods in the function objects. I'm using only call and we'll see that there are others like apply or bind, etc.

So, let's take a look at these couple of lines here, line 21 and 22. What I'm doing here is, well, first of all, maybe some of you are surprised to see that I can reference some property called call in a function. Maybe you didn't expect that functions are actually objects that have properties as well. But, yes, functions are objects in JavaScript. So then they have properties that you can use and methods, etc. So when you use function name.call, basically, you are expressing that you want to execute the function. And the call method here has the first argument, and this first argument is what the value for this. Basically, you are telling the JavaScript engine that this equals an object with B equals 22 in this case. So if I run this, there you go, we see that this B becomes 22. Now, since the full property on bar is also the same function, you can also use dot call on it and then do the same thing again. And then you can pass a whole different context to it as well. So as you can see, methods like call let you set a specific value for this. There are others like someone in the chat suggested you can use bind. I'm going to copy their example. There you go. And you can also use full function apply and then something here. And all these things work. And finally, I have this final example here. I hope that you can see what I'm doing here. That I'm calling the function with the same object as context, which is redundant. This is basically the same thing as doing that. So, again, this way to call functions, I don't know how to call it. I don't know if it has a name even. But this way of calling functions when they are part of an object, this is calling the execution, securing the function as a method of the object. Like a method, like what we commonly understand as an object method.

5. Executing Functions in JavaScript

Short description:

These two ways of executing functions in JavaScript are perfectly fine for most scenarios. If you find yourself using call, apply, bind, etc., a lot, it may be worth reviewing your approach. It's important to avoid unnecessarily complicated code and fighting against the language.

Like a method, like what we commonly understand as an object method. And the difference is that this will become the object itself. That's the bottom line here. So, and another note about this is that these two ways of executing functions in JavaScript are perfectly fine for most of the scenarios you will find. If you find yourself calling call, apply, bind, etc., a lot in some project, maybe it would be good to step back and take a look and review these in case maybe you are doing things in too complicated way or maybe you're fighting. It feels almost like you were fighting against the language in this case, so yes, something to think about if you are doing this a lot.

6. Understanding Prototype Chains in JavaScript

Short description:

Objects are collections of key value pairs. When using parentheses after referencing properties in an object, the function is executed as a method of the object. JavaScript knows the value of properties through the prototype chain, which starts at the __proto__ property. All prototype chains end with a null value and the previous prototype is an empty object. JavaScript will search the prototype chain until it finds the property or returns undefined. Properties can be inherited through the prototype chain.

So finally, let me check my notes real quick. So as a recap, right? First, objects can be thought of as collections of key value pairs, keys are called properties, and anything can be a value really. And then when you use parenthesis, like here, after referencing some properties in object, you are going to execute that function as a method of the object. So then this becomes something else. This becomes the object.

Now that we know about the structure of objects and how to reference properties, the next question we need to be able to answer is how referencing properties works, and to answer that, like, why does JavaScript know that a equals 44 when I do this, right? And why does it know about other properties like this one, right? A.toString. I didn't describe a toString property in full. Sorry. This is not a. I intended that to be full really. So I'm not describing I'm not creating a toString property in full. So why does this work? And to answer that, we need to start to look at the prototype.

So JavaScript is an object-oriented language that is, that bases, like, it's based on prototypes. It's not based on classes, really. On prototypical inheritance, right? And the way this works is that every object has a prototype chain. And that prototype chain starts at the underscore underscore proto underscore underscore property. This is a special property that all objects have. Almost all objects have. Oh, shit. I'm So let's remove all this and run this example here. I'm going to remove all the console logs here to clean up the outputs. Cool. So this console dot beer method will show us the general structure of objects like here I'm seeing here. This is an empty object. is nothing really to show about this object. Just a couple of empty curly brackets. But then the next step, like this would be the property on this object that starts the prototype chain, we see this output here. And here we are seeing that this is an object with null prototype that is providing some methods, for example, or some properties, for example, the Constructor property, ToString property, value of etc. And it itself has another property with its next, you know, step prototype chain. And then the last line here, the prototype of the prototype, is just a null value. So the first thing to notice here is that all prototype chains will end with the same two steps. The last step is always a null object, or sorry, a null value, and then the previous value, the previous prototype is an empty object. And that's the reason why when I do foo.toString, this is working, because toString is not defined in the object itself, it's defined in the first step in the prototype chain. And JavaScript will try really hard to not return undefined on you. It will search through the whole prototype chain until it reaches null. And then Yeah, it returns an undefined, because if by this step here, it doesn't find your property, then it's not a fine. That's basically how it works. Let's see the chart real quick. Also, another. Yeah. Or object with prototype of bar. Yeah, there you go. Um, cool. So then the prototype is about a chain that starts in this property here, underscore underscore protocol underscore underscore. And it always ends on a null value, and then the previous step is always an empty object. And that's why we have some properties that we don't have to define every time they are inherited. And I mean, what in here they are inherited, uh, because some step in the prototype chain has them. And then JavaScript will use that instead of, uh, just, you know, looking at the object and say, no, it's on the phone. No, no. A step in the prototype chain has that.

7. Introduction to Inheritance and Classes

Short description:

So we will use that for now. This is really complicated way of doing inheritance. Let's make a small experiment. If we try to print on screen the a property of the bar object, it's going to be undefined. And also we know that the A property is not provided by anyone in the prototype chain for this object. And then what we are doing here is we are using foo to be the prototype or the first step in the prototype chain of the bar object. And then if we do the same thing again, since foo now is providing a value for A, this is going to stop being undefined. So now let's talk a little bit about classes. Classes don't exist in JavaScript. We have the ability to describe classes because there's syntax for it, but it's only syntax. There are also some security checks in place if you use classes, and that's why we will end up using them. To understand why we have classes today, first, we need to go back in time and do stuff like we used to do when there was no class syntax in the language. Let's consider the second file here, part2.js. So here you can see the stuff we had to do before there were classes in the language. You would have to create some function called the constructor function, actually. This function will do stuff with this, it won't return anything. And then, the function itself had some prototype property where you would create stuff. And then, we are basically trying to get a new instance of person, call it new on the function with the argument. And then, you would use that object as normal object in any other language, you would call methods, provide arguments, etc. So this works, right? But how does this work? With these lines, what I'm trying to do is to see the structure of the object and the first step in the prototype chain, and then the second step and the third. So if I run this, we get the console log from the invocation here on line 10. Then the first console.dir execution is giving us person with name Guillermo. Then the first step in the chain is an object that has a constructor property that is a function and a grid property that is another function. And then the last couple of steps are the end of the chain with an empty object and the null value as expected. So what changes here from the object that we've seen so far in previous examples is that we have this step here providing the grid method, the grid property here, and this is because we executed the person function with uppercase P with a new keyword in front of it. This way of calling functions is intended to get new instances of some class.

So we will use that for now. Um, So this is really, I guess you're all saying or thinking that this is really complicated way of doing inheritance. Some other languages, uh, have this notion of classes that are easier to understand probably, and, uh, they don't have things such as, uh, underscore underscore proto, or things like that are really, uh, weird, but yeah, I don't know, this is how they designed the language initially.

Let's, let's make a small experiment. Um, So oops again, right. If we try to print on screen the a property of the bar object, it's going to be undefined, right? Because bar here doesn't have an A property. And also we know that the A property is not provided by anyone in the, in the prototype chain for this object. And then what we are doing here in the, in line 17 is we are using foo that we declared up here to be the prototype or the first step in the prototype chain of the bar object, right? And then if we do the same thing again, since foo now is providing a value for A, this is going to stop being undefined. We can take a look now. I'll just save the file. And run the file. And now, as you can see, the first log is undefined. The second log is not undefined, it's 44 because A is provided by someone in the prototype chain. Okay. So I hope that. That helps you understand how the prototype chain works, where does it start, how referencing properties works, et cetera, et cetera.

So now let's talk a little bit about classes. Right? So let me tell you that classes don't exist in JavaScript. So I'm sorry, but that's the truth. We have the ability to describe classes because there's syntax for it, but it's only syntax. There you go. Someone told that in the chat. It's syntactic sugar for you. Like, it's to make your life easier. There are also some security checks in place if you use classes, and that's why we will end up using them, and I will tell you that please don't do anything else than using the class syntax for this. And now to understand why we have classes today, first, we need to go, like, a couple of – well, not a couple, maybe more than a couple years back in time and do stuff like we used to do when there was no class syntax in the language. So let's consider the second file here, part2.js. I've jumped to that file. So here you can see the stuff we had to do before there were classes in the language – well, there were the class syntax I meant. You would have to create some function – and the convention here was to use uppercase for the first letter in the function – and this would be called the constructor function, actually. This function will do stuff with this, it won't return anything. Like this is a special function, right? Some function that doesn't return anything, and do stuff with this and nobody really knew what this was really at this point. And then, the function itself had some prototype property where you would create stuff, like read here is a function that receives an argument and does stuff with it – and then, well this is probably the most regular, like normal thing that we are doing, we are basically trying to get a new instance of person, call it new on the function with the argument. And then, you would use that object as normal object in any other language, you would call methods, provide arguments, etc. And I bet that this is almost normal, but this is like what does this mean, right? So this is how we have to do things. And let's run it real quick to prove that this actually works to you. So, well, never mind this console deal code here that is just here to showcase, to show you what is being received as this. So this is what the console says. But then, yeah, in line 12, we call read. And then we have the console log right there. So this works, right? But how does this work? There you go. So with these lines, what I'm trying to do is to see the structure of the object and the first step in the prototype chain, and then the second step and the third So if I run this, we get the console log from the invocation here on line 10. Then the first console.dir execution is giving us person with name Guillermo. Basically, this is what the language is telling you about the subject that is a person with a name property, with value Guillermo. Okay. Then the first step in the chain is an object that has a constructor property that is a function and a grid property that is another function. And then the last couple of steps are the end of the chain with an empty object and the null value as expected. So what changes here from the object that we've seen so far in previous examples is that we have this step here providing the grid method, the grid property here, and this is because we executed the person function with uppercase P with a new keyword in front of it. This way of calling functions is intended to get new instances of some class. And I'm erc working here again.

8. Understanding the new Keyword and Prototype Chains

Short description:

And this new keyword here will change, will completely change the way this function behaves. We are seeing here that is some person, some empty person, really some empty object. So new must be creating that object for us and passing it down to the to the function for us. And this is because JavaScript knows that we got this object out of the person constructor function. And basically what this is doing is well. So why is this here and what is this? This is the prototype property of the constructor function. This is going to become the first step in the prototype chain of this new object. The underscore, underscore protocol property, like the start of the property prototype chain in the new object is the same thing as the prototype property of the function of the constructor function. So this is the way it works. You have to create some function. Then the function would be used to set the state of the new object, like set the name here in this case, then you would create stuff in the functions, prototype property, and then you would get new instances using the nuclear word. And that's why basically you can call Guille.grid, Javier, even though Guille doesn't have the property grid. The property called grid is provided by the prototype of the constructor function.

And this new keyword here will change, will completely change the way this function behaves. Like you can see here for example that this is not some global object or it's not some object that we know of. We are seeing here that is some person, some empty person, really some empty object. So new must be creating that object for us and passing it down to the to the function for us. And then when we print the object on the console, we are getting this person thing in front of the object that shows the properties of it. And this is because JavaScript knows that we got this object out of the person constructor function. And basically what this is doing is well. Yeah, let's continue. So why is this here and what is this? So the I mean, the new step here in the prototype chain. So basically this is the prototype property of the constructor function. This is going to become the first step in the prototype chain of this step in the prototype chain of this new object. I hope you can see that this is really complicated, so it's completely normal to be lost already, but I hope that you can see now that this is going to be true, like what I wrote here, the underscore, underscore protocol property, like the start of the property prototype chain in the new object is the same thing as the prototype property of the function of the constructor function. And if I run this with a console.log, I hope to get a true while you hear. Let's see. There you go. True. So this is the way it works. You have to create some function. Then the function would be used to set the state of the new object, like set the name here in this case, then you would create stuff in the functions, prototype property, and then you would get new instances using the nuclear word. And the deal is that you will get a new object and that object will have the prototype property of the constructor function as the first step in the prototype chain of that object. And that's why basically you can call Guille.grid, Javier, even though Guille doesn't have the property grid. The property called grid is provided by the prototype of the constructor function.

9. Understanding Class Syntax and Usage

Short description:

The class syntax was introduced in the language to make things easier and prevent dangerous practices. Calling the constructor itself or without the 'new' keyword can lead to unexpected behavior. It can change the object itself or pollute the global context. The 'use strict' directive can help prevent such issues. The class syntax is similar to other languages, with the 'class' keyword and a 'constructor' method. Creating new methods is straightforward, and the usage is the same as before. Overall, the class syntax simplifies object creation and usage.

OK. This is very confusing. Don't worry too much if you are a little bit lost at this point it's perfectly normal. The bottom limit is that that I'm showing you this to sort of justify why we have the class in text and hopefully to now be able to understand that a little bit easier. The reason why we don't use this anymore or the reason maybe probably The reason why they introduced the class syntax into the language is because you could do all sorts of stuff that would be dangerous for you. Like for example, you could call the constructor itself, referencing it from the object. And this would change the object itself, which is really confusing, now the Object has a bar name, and this is really unexpected, because you are calling some constructor. Then maybe you would expect to get any object or anything like that. This doesn't make sense at all. Dangerous stuff to do. Another thing you could do is take the constructor and call it, with something weird like this one, like in this instance, and then expect this object to be something. This doesn't work of course. Javier is going to be undefined because the constructor function is not returning anything. It doesn't use the return keyword. So anything you try to assign... this is not going to work the way you expect it. And this is really the most dangerous thing you could do with a constructor function, is to call it without using the new keyword here. Like I'm not using new. This is really dangerous and this was one of the main pains that this would create. And this is dangerous because if you don't use new, then the language will assign this to be the global object. Like here you can see that this is the global object, like you can see here. And then what this means is that this is going to be run and we are basically adding some name property on the global object, which is, you know... It's called polluting the global context and this is something that everybody agrees that is not good to do. And then you won't get anything again because person doesn't return anything and then Javier will be undefined, you can see here. And then the name property on the global context will be set to something. So imagine that you are doing this a lot and then a couple of constructors use the same property name. So the last one that you execute is going to overwrite the value and all sorts of wrong behaviors you can expect and this is really hard to debug too. So yeah. Everybody agreed that having to go through all these hoops just to get one object was a bad idea but designing the language so they introduced class syntax. Exactly, yes. Someone is also mentioning the use strict directive or keyword, I don't know how to call it really but I bet you've seen this somewhere already. This is something you put at the start of the script and then the language will prevent you from doing crazy stuff like this, will actually complain but you need it to not forget about doing this. So to make things much, much easier for everyone the language introduced the class syntax and I hope we can all agree to that. This is much easier and much nicer for to get the same result, right? First of all, we are using a syntax that is very similar to other languages. You have the class keyword here. There's some special method. In this case, it's called constructor. In Ruby is called initialize. In Java is called the, has the same name as the class. There are different languages have different conventions but we can all agree that it's easy to spot. This is the constructor that we are going to use. And then the syntax to create new methods is nice too. There are no strange prototype properties. Yeah. Nothing really. Everything is looking fine so far, or I hope it is. And then the usage part is exactly the same. You use Neo on the class name and you just use the methods here. And the result is also the same. Like if I run this file now, it's part three.

10. Syntactic Sugar and Constructor Invocation

Short description:

If I run this, I get a person with a name property with Guillermo. Classes are syntactic sugar that provide safety by enforcing the use of 'new' when invoking constructors. It's important to use this syntax correctly to avoid issues in the long run.

If I run this, I get the same thing. I get a person with a name property with Guillermo. I get a first step of the prototype chain that looks very similar than the one that I got with the prototype chain. And then the last two steps are the null value and the empty object. Everything is looking fine. It's not exactly the same. If we went into to analyze this with the debugging session, et cetera, we will see it's different stuff, but overall it's the same concepts apply. And here you can see also that classes are really syntactic sugar because under the hood what you have is a prototype chain just like the same you had before. And here is the best part of this is that you get a lot of safety out of it. If you try to use the constructor in isolation, well, not in isolation, invoke it as a method, the language will complain. It will tell you that person cannot be invoked without a new. If you try to run it in isolation without a call, it's going to complain too. Same stuff, you need to invoke it with new. And if you try to call the constructor function without new, it's going to complain too. So much, much safer to use this syntax. So that's why in general, I would tell you, please don't ever try to do anything like this unless you are super like, you know what you're doing basically because it's going to be bad for you in the long run. Cool, there you go, cool.

11. Difference between Invoked and Code in JS

Short description:

In JavaScript, the terms invoked, executed, and called are synonymous when referring to code. The 'call' method on functions allows you to pass a context and arguments as comma-separated values. On the other hand, the 'apply' method requires the arguments to be in array form. Both methods have their uses, depending on the situation. Overall, they all refer to the same action of running code.

So someone is asking, what is the difference between invoked and code in JS? I think it's a synonym. You can use like, when talking about code, invoking a function, calling a function, executing a function, it's all the same. Maybe the verb call has a special meaning because there's a call method on functions. Let me show you that. So full function.call, we've seen that, right? You can pass it a context. And this has a special meaning because if full function had some, I'm going to remove all this just to make room and be very specific about this. If full function has arguments, A, B, C, and you are trying to invoke it with call, then you need to provide the arguments as comma separated values. Whereas, for example, if you would use apply, the first argument is the same, but then the arguments of the function itself need to go in array form. Sometimes it's easier to use apply because maybe you are getting the arguments from some other function call and they are already in array form. So doing it like that is more appropriate or more, you know. Just options you have, call and apply. But yeah, invoking, executing, calling, whatever you want. I think it's the same. I hope that answers your question.

12. Object Literals, Classes, and the Module Pattern

Short description:

Object literals and classes in JavaScript did not have the ability to hide information until Node.js 12. With Node.js 12, you can declare private properties in classes using the hashmark prefix. These private properties can only be accessed within the class. The language prevents access to private properties from outside the class, providing a higher level of security. Before Node.js 12, the module pattern was used to hide information. The module pattern involves using functions that return something, creating a local scope where functions and variables are declared, ensuring that they stay hidden outside the function.

Okay, so again, let's go to part three, part four. Again, how to get yourself an object. We already used the, this notation here. Right, so this is called object literal. And this is probably one of the most easiest way to get an object, you just open a curly brace, then put the properties, a colon and then the value and you can have more of them. And yeah, that works and you can even, whoops, that's not what I wanted to do. You can even have methods and now it's probably better if I format it in a way that is easy to read.

All right so this is the object liter notation, one of the easiest ways to get an object. Another one is the using classes of course. Well, someone is, someone in the chat is mentioning object dot create so we will get there at the end. And we can talk about that later. Yeah, it's, okay, so object literal, using classes to get new objects from it. But then what happens here is that both object literals and classes until Node.js 12, version 12, didn't have the ability of hiding stuff. Everything was public. Every object, you as the user of that object would have access to everything that is declared in that object. And I don't know if you know that, but in object-oriented programming, encapsulation is a big thing. You would have or you should design your classes and objects in a way that encapsulates the internal implementation details of that object and only exposes a public API or a public set of data that users should use and not the internals. That's basically encapsulation. And in JavaScript, before Node.js 12, if you were using classes or you were using object literals, you wouldn't be able to do that. You would be forced to design your assets, making everything public and maybe probably having some conventions about putting underscore in front of a property name, maybe to indicate that you shouldn't use that or whatever but there were no hard rules about this. This was especially problematic when dealing with objects coming from frameworks and libraries. But after Node.js 12 it turns out that you can actually have private stuffing classes. And the way this works is by using the, well, this is called the hashmark. For some reason, they call this hashmark. So let's roll with it. So you declare the name property to be private by prefixing the hashmark. And then what you get is, you will be able to reference that property with the hashmark, whatever inside the class, but not outside the class. The language will prevent you from accessing that. So let's run this first to see that it works. There you go. And right off the bat, you can see that when I console.lock the object, I'm not seeing anything about the name property. And being JavaScript, the language it is, where you can basically do whatever you want in memory, like in runtime, you could think, okay, I know that name exists. I'm just going to add a method on the object dynamically that returns it and that's it. And this should work, right? Well, I have bad news for you. This is not going to happen. And this actually is a pretty well, pretty good safety standard in place, I think because it's going to tell you that name is private and you need to declared this method in the object. Sorry, in the class. Basically what this is telling you that is that you need to have access to the source code and you have to be able to deploy the source code in wherever this is running. So these are, this is a high security standard in my opinion. It's not like, this is a maturity sign to me. The language is getting really mature in some way. So yeah, starting from with Node.js 12, you can do this. So yay, this is good news. Before Node.js 12 though, how would you deal with this? Sometimes you couldn't deal with this because you actually needed a class. Maybe this was a model that was going to be instantiated a lot of times, so you really needed a class to make the whole process lightweight. But sometimes, you were designing some service that you are going to instantiate only once, right? So, when that was the case, and we are moving to the part five file, you would use the module pattern. And the module pattern in Node, in JavaScript, it's just about using functions that return something. And what you get from doing this is every time you open the curly bracket here to start implementing this function, you are getting a local scope where you can declare functions and variables, and none of that will escape that local scope, meaning that outside the function, whatever you create inside that function is going to stay hidden away. Like nobody is out of reach, right? Sorry. So by following this structure here, what I'm doing here is I'm creating a function I'm creating a function called gritter with capital G that returns another function, it's anonymous, doesn't have a name.

13. Encapsulation and the Module Pattern

Short description:

The gritter function receives a name and returns a function that takes another name and prints something in the console. The value of the name argument is encapsulated and made private. The function instance is identified by the language and included in the prototype chain. This construction is commonly used when designing services. The module pattern allows the creation of private and public elements. The object returned includes the closure that pulls all the necessary values. The module pattern is a way to implement objects where everything is private by default. The prototype chain is updated accordingly, and the module pattern can be executed without polluting the global context.

And the gritter function receives a name. And the function that I return takes other name and prints out something in the console. So the deal is that once I call the function with capital G, I get the function and at this point, the name argument like Guillermo, this value here is out of reach. Nobody can buy through manipulation of the Gritters Guilli object, nobody can reach out that value. I'm hiding that, I'm encapsulating that, I'm making that private and I'm air quoting here. And that's basically the way to deal with that. I'm using functions and the locals variables, variable scope of functions in order to hide away stuff and only return or publish or make public or whatever I'm returning. And if I run this and take a look to the prototypes, et cetera, what I'm going to see is, well, this is the line that I get from calling the function itself. But then, yeah, the last two steps are what we expect, the null value and the empty object. And then there's a third step, a special step here. Then, and this is, this is the function instance. Sorry. Basically, the language will identify this gritter, sorry, this gritter sguille variable as being a function by putting this in the prototype chain. And by the way, this is also what is providing me with applied bind and call methods that we already talked about. Cool, so maybe this is like, it's hard to see the value of this construction with such a simple module here. But if we hop into the next file, part6.js, you will see that this is actually that something that I did all the time. Whenever I had to design a service, I would do it like this. I would create a module for the service, I would create stuff here, and then at the bottom of the module, I would return an object. And that object is the API of the service. And here, what I'm doing is, I'm creating three functions. And I'm returning only two of them, create and save file. Well, I'm returning an object that has a property that has a value of a function that is declared in the local scope of the reader two module. Right? Mm-hmm. Yeah, and the object that I'm returning here is pulling with it the definition of the log function. Because, you know, the object depends on grit and grit depends on log. And log doesn't depend on anything. So this works because the object that you return includes the closure that pulls all the values it needs to work. And you could here do anything you want, like create const A 42. And then use it here. And nobody is going to have access to A unless you explicitly publish it through the object that you're returning. I hope that this makes sense. Like, the way to make it public is to include it as a return value. So basically, in some sense, this is a way to implement objects or describe objects in a way that everything is private by default and then you choose specifically what you want to make public. Yes. Cool. So if I run this five now. Let me clear the screen. What we see is that now the prototype chain has the, well, as always, the null value was last. Before that, it's the empty object and now we have the, the greater object has a greet property and a say goodbye property, as we expect. And yeah. Just to a couple of notes about the module pattern here. You have a couple of examples in part seven, that's JS. The first one here is called the self-execution executing function. I bet that most of you have seen some form of this somewhere. This is... a way to declare a module and execute it without polluting the global context. Because this function doesn't have a name. Doesn't need a name. Because we are executing it with this parenthesis right after declaring it. So it doesn't need a name.

14. Objects and Modules in JavaScript

Short description:

Therefore, objects in code transpilation and packaging software are wrapped with self-executing functions to prevent pollution of the global context. Node.js uses a module wrapper to provide arguments and wrap around files. Understanding prototype chains is useful for troubleshooting issues in systems and working with objects from libraries and frameworks. Depending on the need for multiple instances, classes or modules can be used. Modules, which involve functions and variable scopes, can be a simpler solution in some cases.

Therefore, it doesn't need to be stored in the global context in any way. It will just, you know, declare it and run it. Both things in sequence. And there's no pollution of the global context. This is also the way that most code transpilation and packaging software works, like Webpack and others, will take your TypeScript sources. Or whatever language you're using these days. They will take that, transpile it, and put it, wrap it with self-executing functions so that when it's delivered in a browser this is executed and there's no side effects in the global context either.

And the second example here is what Node.js actually uses to wrap around your Node.js files. This is the module wrapper. And you can see here that it will receive the exports, require module, and other arguments that are available in your files. Like they are being provided by Node.js when it wraps around your file with this self-executing function.

And yeah, with that, we have hit all the contents I wanted to go through about the objects. We have still a question to address. And before we do that why I think this is useful for me, this is useful, especially with troubleshooting issues in systems. And especially when objects are coming from libraries and frameworks because when you are with the final end-user system, your design tends to be more flat, probably, and the type hierarchies are flat there. So there's not much going on in the prototype chain. But when you are dealing with objects that come from frameworks and libraries, frameworks and libraries are designed to be reusable and abstract and that is achieved in many ways and some of them have to do with complex type hierarchies that require complex prototype chains. So when you get one of those objects, it's really useful to know your way around prototype chains and things like that and knowing how instantiation works because when there's an issue with those subjects, you can go in and get to the answer quicker if you didn't know that of course. And then, a second way that I think this is useful is because now I can ask myself when designing a new system, I can ask myself, am I going to need a lot of instances of the same thing? So then, I would probably have to design a class because having a prototype chain is a faster way of making sure that all objects have the same methods and properties. Maybe I'm going to have only one instance of it, it's a Singleton or a service or something like that. Then, I can probably get away with just a module. And, this is also, like everybody can think differently here, but I think that these modules here, since it doesn't have to do with prototypes or classes or inheritance, you don't need to use new at all. This is just functions and variable scopes. To me, that brings less complexity to the solution. So, it goes more in the style that I like, then maybe I will use this instead of using a class that only I instantiate one object out of it. But now I have options and that's what I value really. And now would be a good time if you have any questions, you can ask it in the chat on Zoom.

15. Using Object.create in JavaScript

Short description:

Some people think that using object.create with null is faster and has a smaller memory footprint. However, in most scenarios, it is considered over-engineering. Object.create with null creates an object without a prototype chain, which can cause issues with certain methods. Object.create and Object.assign are useful in specific scenarios, but understanding the ObjectLiteral, class instantiation, and modules are the main ways of creating objects in JavaScript. Object.create is more suitable for advanced use cases like designing video games or working with lightweight objects.

And I have one question from someone that is asking, have you seriously used object.create with a non no prototype in production? That's a really good question. It's, in my opinion, it's a very advanced topic to talk about probably. But yeah, let's try it, okay? So this person is referring to these thing you can do, object.create, oops, create. No, that's not what I meant. And here, if I'm not mistaken, you can pass the prototype here, right? If I pass null here, and I assign that in a variable like that, and then I do console.dir a, and then I try to do that, and I run it, there you go. So, a is an object with null prototype, and the prototype property of that object is undefined. So, basically, what we are getting by doing object create with null is an object that doesn't have a prototype chain. Some people think that this way of creating objects is faster, it has a smaller memory footprint. This might be relevant when you are dealing with a highly efficient code that needs to go really, really fast. I would say that in 99.9999% of the scenarios, of the scenarios, this is like over-engineering it. Like, why don't you just, you know, what is the problem of doing that, right? But another side effect of going this path is that now A to string is nothing, and this will fail. There you go, A to string is not a function, right? uh. Yeah, so some people is answering because you are not dragging the default properties or I would use it to guard against unsafe input prototype chain. Oh, that's a really good point, yeah. Well, those are valid points, if that's your scenario, go ahead and use it. These two tend to go together, like object create and object assign. I encourage you to investigate the research, learn about them. They are there because they are useful in some scenarios. I would, normally, what I would argue is that the ObjectLiteral, the class, whoops, instantiation or just, you know, calling a module that gets you some ObjectLiteral are the main three ways of creating objects that everybody would have to understand and master. And then if your scenario requires more, yeah, why not? ObjectCreate is there for you. And ObjectAsign, if needed. There are tools that you can use. But yeah, this is honestly, this is advanced stuff. Maybe you are designing video games in JavaScript or maybe you're doing machine learning stuff or, I don't know, maybe your use case creates, requires really lightweight objects and that's useful or maybe for validation or someone... and safety as someone suggested.

16. Introduction to Asynchronous Programming

Short description:

JavaScript provides a single thread for programs, which queues and executes instructions. Other languages have a multithreaded approach, allowing for more control and resource usage. However, this comes with added complexity and debugging challenges. JavaScript simplifies the process of working with non-blocking asynchronous programs. Let's be happy about it and move on.

Okay, so first of all, well, my goal for this section is to convince you. If you are not convinced already of course that actually JavaScript is a really good language to work with non-blocking asynchronous programs. And first, we need to establish that this is something that we actually need. Like, why would anyone do that to themselves? Right? And it's, like this is required, like we can't really work around these. Input output operations are slow and we can't have the thread blocked while you're fetching some data from a third party server or writing some files down in the file system. You can't have the CPU stopped just waiting for that to end. And this is especially important when dealing with UIs, right? It would be a very bad user experience if the screen would freeze when some drop down is loading the items to choose from. Nobody does that these days like applications tend to be asynchronous because it's just better. So JavaScript solves this like there are multiple ways of solving this problem, right? In JavaScript, what JavaScript does, it provides you with a thread, a single thread for your program, and then every instruction that needs to be run goes to that queue, and what the engine does is goes through that queue until there's nothing else to be run, and then it stops working. So when you're writing a JavaScript program, what you are basically telling JavaScript is what instructions need to be queued and the order in which that needs to happen. Other languages, like Java, for example, have a multithreaded approach, and that approach is probably much more powerful, lets you have more control, and more importantly, lets you use all the resources that you have in the server or the computer that your program is running at. If you have eight cores, you can really, take everything from them, get them to be running at 100% of time occupation, of time occupation, and really, you know, extract all the power from the platform you are running your program. In Node.js and JavaScript in general, you don't have that option. You only have one thread. If you have 10 cores, you will have to use something on top of your Node.js program to extract all that power from the platform. So you have only one thread, and other languages let you access all the threads you can get from the platform. But the trade off is that they bring a lot of complexity on you. You need to be a really expert programmer to design programs in a way that are easy to understand and easy to maintain. And also another trade off is that when things break, a multi threaded program is much harder to debug than you know, you get into bigger issues probably. So, first, like right in the introduction, I'm telling you that the bottom line is probably we should be happy about it. JavaScript solves this hard problem to solve in a simple way. I know that it can be overwhelming at first, but I hope that with the things that we are going to see now you will have the tools to think about it in a more efficient way and simpler way. But yeah, the bottom line is it could be worse. Let's be happy about it. JavaScript is awesome. Let's move on.

17. Understanding Asynchronous Behavior in JavaScript

Short description:

In JavaScript, non-blocking behavior is described through callback functions. We will play with the setTimeOut function to understand it. The order of execution is A, C, D with a delay of one second between C and B. In the second file, the thread is stopped for two seconds, and the sequence is A, setTimeout of B with a delay of one second, and C. Can you guess the sequence and how the delays will play out?

All right, so in JavaScript, non-blocking behavior or asynchronous behavior is described through callback functions. And these are functions that are going to be called sometime in the future back. Like, that's literally they mean that, right? And to get the hang of it, let's first play with some piece of code that I have here. Let's go to the async directory on part1.js file. Let's see. Yeah, so we are going to play with the setTimeOut function. And the setTimeOut function let's you... lets you put here a function, and some delay. And what you, like the promise is that this function will be called in no less than 1,000 milliseconds, one second here. Oops, somebody changing that directory. Oh. Okay, cool. So again, this code here is going to print A. Then it's calling setTimeOut on a function that will print B. And then it will print C. And here are the challenges. Can you guess the actual order of these slugs? Like I will let you think about this for a minute. You can go and run it in the terminal too if you want to see what actually happens. But I would, let's try to... First of all, before running it, let's try to make a guess. Okay, so someone is already making bets in the chat. A, C, D, for now, B, A okay. I don't know what was that. A, C, D, cool. Cool, so let's run it. I guess we can actually see it, right? A, C, part one. Cool, so the order is A, C, D. There you go. A, C, D, you all were right, I guess. The interesting part here is that there's a small delay between C and B because we can see, right? The setTimeout is setting a delay of one second. So this is expected. A, C, one second, then B. Okay, everything is fine. Nobody made a different guess so I think we can move on to the second file. And here in this file, what I'm doing is, I'm using this module here called sleep that is going to actually stop the thread and prevent anything from running for two seconds. And here, notice that two seconds is more than one second, right? So, and it's the same sequence. Console log A, setTimeout of console log B. One second of delay. Stop the thread for two seconds and console log C. Again, I'm going to reset here. Make a bet, like what's going to be the sequence. Maybe you can also describe how the delays are going to play out in the end result. Can you guess that? Okay. Okay. So we have the first guess of ACB. Maybe you can explain. Oh, we have an ABC. This is getting interesting. If you can reason also how the delays are going to play out, that would be great. ABC, ABC.

18. JavaScript Event Queue and setTimeout

Short description:

So ABC is winning right now. The order of locks must be the same. The fact that we are not waiting for any millisecond at all doesn't change the fact that this is enqueuing the log first, this is enqueuing the set timeout call, and this is enqueuing the log C. The execution of the setTimeout enqueues this call here. The mental model I follow, the way I think about asynchronous behavior in JavaScript, has to do more with enqueuing stuff like we did here and understanding what is going to be the trigger about. Those are different triggers that will be taken into consideration when that callback is the next thing to run, right?

So ABC is winning right now. Okay, so let's... Cost of node.js lifecycle. Okay. That's true. I think, yeah, the person that guessed ACB is right. Let's take a look. ACB. So first of all, the order is the same. Again, you need to think about this as, there's a single thread and there's a queue of instructions. And the queue of instructions is the same with the only difference that before printing out C we have sleeping for two seconds. But everything else is the same, right? So the order of locks must be the same too.

What is interesting here is that we are waiting two seconds between A and C and then B is printed out right after, almost instantaneously. So what we see there is that there is no an extra seconds delay after we slip for two seconds. Like this is what set timeout does, it's letting me describe a delay that is starting from the last run instruction, well, last encued instruction. So since we are slipping for two seconds, two seconds is more than one. It prints out b instantaneously, it doesn't need to wait more. Okay. Cool, so now let's go to the third example. And here we are not going to block the thread or anything like that, but we are setting the timeout to zero milliseconds. So in your opinion, is this going to change anything? Is the order going to be affected by this? Or yeah, make your bets, I guess.

Okay, so ACB it won't change, still the same. ACB as well. Yeah, so you're right, basically it's not going to change. ACB again, yeah. So you already understand how this queue thing is working. I am happy about it. So ACB, the order is the same, the fact that we are not waiting for any millisecond at all doesn't change the fact that this is enqueuing the log first, this is enqueuing the set timeout call, and this is enqueuing the log C. And then when this is called, you can teach using stack mode, yeah, exactly. When this is called, this is enqueued at the last position, and then, like, yeah, so the stack, by now, has A, now the stack has A, and the setTimeout, I'm just improvising here, and then here, the stack has setTimeout, and then C, and then when this is executed, like, the engine starts, actually, to take instructions and run them, it will take A, and the stack has setTimeout, and C, then it takes the setTimeout, and runs it. And the stack has C, and as a result, the stack now has C and B, because the execution of the setTimeout enqueues this call here. And then, finally, C is taken, B still pending to be run, and then B is taken, the stack is empty, and the program ends. Oh, okay, I hope this improvised. I wasn't planning to explain it this way, but I hope it makes sense. So, anyway. Uh, cool. Yeah, again, the same, I'm just, you know, we are dancing around the fact that there's only one thread, and there's a queue of instructions to be run, and setTimeout is really, you know, it has this very misleading name of timeout when in fact, it's enqueuing stuff with a time-based trigger, or I don't know. The mental model I follow, that the way I think about asynchronous behavior in JavaScript in general, has to do more with enqueuing stuff like we did here, and understanding what is going to be the trigger about. In the case of a setTimeout, it's going to enqueue like it happened here. It's going to enqueue B, but it's B with an asterisk because it's not like the interpreter won't take B out of the stack if not enough time has passed because maybe I need to wait for seconds. If not enough time has passed, B is going to stay in the stack until that time has elapsed and then it's going to execute it once that time has passed. And this is exactly the same when we are talking about a night AJAX call, for example, it's not a time-based trigger. It's a trigger that is based on some input output operation that happens in the network layer when some request is done to some server and then the operating system gets the response and parses it, blah, blah, blah. And then the trigger is like my callback for the AJAX call is going to be that I have the response and the response has to be parsed and then the callback is called. And until that response is available, the callback is going to be in the queue waiting to be executed. Or for example, if I'm writing a file in the file system, the trigger will be about that write operation to be completed. And then, the mental mode, everything is the same. They are just callbacks that are in queued. They are in the queue waiting to be executed and they will be executed based on some trigger and depending if I enqueue to them with a set timeout or an AJAX score or a file write. Yeah, those are different triggers that will be taken into consideration when that callback is the next thing to run, right? That's the way I think about these things.

19. Using Promises for Asynchronous Programming

Short description:

Callbacks can become complex when dealing with multiple operations and side effects. JavaScript's promise API simplifies asynchronous programming by providing design patterns for coordination. The non-blocking function example demonstrates the use of promises to sequence callbacks in a specific order. Chaining callbacks in promises allows for a functional pipeline of functions that process values and pass them down the chain. Promises enable breaking down side effects into smaller chunks and describing the order of operations.

And this callbacks thing works really well. It's simple enough when you are dealing with a single callback that needs to be run, when that callback is simple enough, like it's a couple of lines probably that it's not too complex, but oftentimes you need to do more complex stuff. Maybe you need to run a huge callback that does a lot of stuff, or maybe you need to coordinate a first call to a service and then a second call to another service, and then maybe you need to write something down in a file versus something in the database, and blah, blah, blah. It can get really complicated, right?

And when the operations are done, around that, are synchronous, it's just about writing your program and that's it. But when everything starts with some non-blocking operation, like an AJAX call or reading a file from the file system, whatever, doing that coordination and breaking up every side effect in a small digestible function that deals just with one thing, that's something difficult to do just with callbacks. Like if you are an expert functional programming software developer, you have a lot of tools to do that, composition, function composition, you can have monads, you can have, you have a lot of tools and that's perfect. Perfect. But if you don't have the expertise, or maybe you're working with a team of with mixed levels of knowledge, or maybe there are specialist or functional programming specialists, but there are other specialists that don't have that, that knowledge and they are more experts, I don't know in UX or whatever. And they know about functional programming. And doing that coordination is really complicated and will make things like collaboration is going to be harder for you overall. So what to do then, right?

The bottom line is that you want to use standard design patterns that are applied to asynchronous programming. And the good news here is that JavaScript provides you with a promise API that implements a couple of useful design patterns that let you precisely do these coordination stuff in a more easy way, in an easier way. And we have an example of that in Par4. Like this is a really quick introduction to promises really. And Par4 has probably one of the simplest way of introducing this. Basically, what I'm creating here is a function that is called non-blocking function. It takes some delay and it returns a promise that will resolve once that delay has elapsed. And what you can see here is basically this is just a dropper around setTimeout. Okay. So, yeah. Whenever you call non-blocking function, first of all you get a promise. You can go and assign this into a variable, you can use p1 equals that. And then p1 then, blah, blah, blah. First of all you get a promise. And a promise is an object that represents some asynchronous non-blocking operation that will produce a value, will resolve to a value or will be rejected with an error. And this function returns the new promise and the body of the promise is calling setTimeout to call this function in turn. This gets a little bit complicated but I hope you can all follow. This basically will call resolve with some value once the delay has passed. Cool, so if we only have one callback the value of using promises is not so evident but I hope you can see here that I'm using the then method on the promise. This actually lets me, first of all, like this would be the first asynchronous programming pattern that I want to talk about. It lets me sequence executions of callbacks that will happen, like you are guaranteed that first one is going to be called then the second, then the third in a specific order. So if I do this return 33, for example, whatever that makes sense, I can then call with another, oops, with another value, oops, I can't type today, sorry. Like that. And I hope you can see that what then does is return another promise. Like that. So what we are seeing here is that I'm triggering some operation with a non-blocking operation, and I'm describing a sequence of things that need to happen and thanks to the promise API, I'm guaranteed that all these calls are going to happen in order regardless of when this first promise is resolved. And probably one wouldn't write this like that. One would use the chaining of callbacks like this, which could be nicer for some. But yeah, if I run this, if this is part four, when the delay happens, and then this is run, and then this is run. And another interesting thing about chaining callbacks in Promise is that the callback that is being executed at every time is getting the value of the previous callback. Like the value that the previous callback is returning. This way, what you are defining here is almost as a functional pipeline of functions that start with some value and pass down, do something with that value and pass down a new value to the next step in the chain. Therefore, when you call a non-blocking function with a one, the Promise is getting resolved with that value. So you get a one here, and then you return something else. And the next step is getting that in turn. And then you can keep returning new stuff down the chain to describe whatever operation you are trying to do here. And again, this is letting you break down the side effects into smaller chunks. And this is letting you describe the order in which these things need to happen. When does delayedSeconds will play, I don't get this, yeah I'm sorry, yeah this, maybe the notation is not helping understand things, sorry. Let's write this slightly differently, okay? Because I'm introducing function, oops, oops.

20. Tuning Down Callbacks and Introducing Promise.all

Short description:

I'm introducing here tuning down callbacks. This lets you describe the order, lets you break down the side effects in smaller chunks. Every time you call then, you can actually provide two different callbacks. One to be run if the previous promise was resolved and another one to be run if the previous promise was rejected with an error. This is often used to do error management. Another thing you can do here is to catch. On top of being able to call then, you can also call catch at the end. This is a terminating call. If you have an error callback here and you return 33 for example, you are going to get the flow back to the success path and catch won't be called. First design pattern around the synchronous operation, sequencing of callbacks. In part five, in the next file, you have another asynchronous programming design pattern that is called a semaphore. And this is provided by promise.all. And then you provide an array of promises.

Okay. Is this right? Let's see, there you go. Cool so, do you remember that we did this here? Set time out with a function and a delay. So this is basically the same thing, oops, oops. Where did they go, sorry. This is the same thing here. The same code. So the delay seconds by 1000 is basically letting me say one second, two seconds, and this is what is going to be passed down to the, okay, you get it now. So that, yeah, awesome. Cool. Yeah, so as a recap, I'm introducing here tuning down callbacks. This lets you describe the order, lets you break down the side effects in smaller chunks. And you're guaranteed that this is not going to be called before this is completed. There are other things that this is providing us with is for example, if I type this like that, I actually can do this oops, console error, oh, sorry. So to keep things simple, I didn't do this before, but every time you call then, you can actually provide two different callbacks. One to be run if the previous promise was resolved and another one to be run if the previous promise was rejected with an error. And this is often used to do error management, right. And you would do things like log the error like this or maybe you can return some default value. You know, these kind of default values that you could choose to return in case something goes wrong. And this, what effectively is doing, like this promise was rejected, right? And then this callback was called. So by returning something here, what we are effectively doing is recovering the flow of the premise into the success path. Like we went to the error path because something was rejected, but by returning something we are forcing the flow back to the resolution flow. To continue, you know, executing the change of side effects through the success path, whatever. Another thing you can do here is to catch. What happens if you provide another function and also catch at the end? Okay, that's what I'm going to do. So the catch, catch, one so, what is going on? Okay, so you, on top of being able to call then, you can also call catch at the end. And this is what is called, well, I'm not sure if this is the precise name, but this is a terminating call. Like you can't go and then anymore after you call catch, okay? This is terminating the chain of side effects. And this is letting you do a final error management. Like if you don't have any error path callbacks, it's not required to provide an error callback, this is optional. So you could only get about the success path like that. And then write the catch here at the end. And this will, regardless of what it failed, what it was rejected, this will be executed. What if you have an error callback here and you return 33 for example? Well, if you do that, which I believe the syntax is not right because I'm using return here, it forces me to do that. If you do that, you are going to, you are going to get the flow back to the success path and catch won't be called. Only if an error is not managed by an error callback, reject callback, then the catch is going to be executed. If the error function doesn't return a rejected permissor throw, the catch will never be called. There you go. That's the much better explain. Thank you. Cool. So first design pattern around the synchronous operation, sequencing of callbacks. There you go with the then, and the catch, and the resolve callbacks, and the reject callbacks. You can error manage in a very structured way, super useful. In part five, in the next file, you have another asynchronous programming design pattern that is called a semaphore. And this is provided by promise.all. And then you provide an array of promises. Are you telling something about view engines and node.js? I prefer to know about AGS. No, I'm not going to touch that. Sorry.

21. Understanding Semaphores and the Race Pattern

Short description:

This is called a semaphore, which is a promise that will be resolved when all the promises have settled. It guarantees a specific order of values and eliminates uncertainty in asynchronous operations. Another useful pattern is the race, where promises compete against each other, and the callback is called with the value of the first resolved or rejected promise. The program still waits for the completion of other promises, even if one has already been executed. The promise implementation is complex, and there are nuances and cases that can make it even more complicated.

This is only about objects and asynchronous programming. I'm not going to talk about any view engine or anything like that. No, no worries. Cool.

So again, this is called a semaphore. You call it by using the old methods in the promise subject, and you need to provide an array of promises. And what this is going to do, this is going to get you a new promise, P1. And what we are trying to describe here is that P1 is a promise that will be resolved or rejected. Well, resolved maybe, it's better. When all the promises have settled. When all promises have been resolved. And then and only then, the next side effect will be, the next callback will be called. If we were in this example, whoops, like this not the file, there you go, one, two, three, boom. And you get the callback called.

And so notice a couple of things here. First of all, this promise is taking one second to be executed. This one two, and this one three. Since I'm waiting for all of them, this one is going to take at least as much time as the lowest of all of them, right? And the second thing to notice here is that the callback here of P1, the arcs of this callback is going to be an array of values, and each value in that array is going to be the partial value of each one of the promises that compose the semaphore. So it's getting one, two, three. In order two, it doesn't, like, if I did the opposite order. Well, this is formatting the code in a different way, but, yeah. I'm setting in a different order, right? Three, two, one. If I run this again, I will get three, two, one. It's not about who is fastest or anything like that. It's about guaranteeing that there is some relationship between the way I write the code and the order I get the stuff here as values. This is super useful because it's taking away a lot of uncertainty from an asynchronous operation that is always hard to reason about. This is letting you describe things in a very precise way, an explicit way. So there you go. This is called the semaphore. You call it with Promise.All and gets you a new promise that will be resolved once every composing promise gets resolved. Therefore, it will be as slow as the slowest of them. Cool. The next, the same pattern that I wanted to mention is the race and this is super useful. I hope you can see this by the end of the, of showing this around. The race lets you literally race a couple of, a set of promises between each other. And what this does is basically the callback is going to be called with the value of the first premise that gets resolved or rejected. Um, since I'm running one, two, three, one is going to win, of course, and then one is executed there. And then the program still needs to wait for the completion of these two calls because these are un-queueing stuff in the queue. Okay, so someone is saying something in the chat. Okay, and sorry, but about the catch description about if the first promise resolution handler throws, not only the first error function, catch will also be called. Yeah, of course, yeah. As I said in the beginning, there's a lot of nuances going around. And actually, the promise implementation is deeply complex. There's a, like, yeah, once I tried to implement a promise engine and it's, like, the basic stuff you get to understand and it's intuitive, but it can get really complicated, really, really, really quick. But yeah, there are cases where you, even if you have a rejection callback, blah, blah, blah. It can get really complicated. I'm sorry, but yeah, there's not much time to go through that. Going back to the race here, what you see here is that even though the promises is resolved really quick like after one second, the program takes a little bit more to complete and that's because these two calls here still have to Queue stuff and those instructions need to be executed. So that means that the program itself will take three seconds waiting for this one even though the call that was two seconds ago was executed. So that's why we are seeing the delay here after the one is printed out.

QnA

Implementing Timeouts with Promises

Short description:

And this is a really useful design pattern because it lets you implement timeouts. If we define a function called timeout, we can create a race between a timeout and a non-blocking function. Timeouts can be implemented using promises, and the 'race' method can be used to determine which promise wins. The 'any' method is similar to 'race' but waits for any promise to resolve before rejecting the whole promise. This concludes the contents of the workshop. If there are any questions or code snippets you'd like to discuss, feel free to ask. Thank you all for attending!

And this is a really useful design pattern because it lets you implement timeouts. And basically a timeout, what is a timeout, right? A timeout is a race between a promise that will be rejected after some time and your actual logic that you need to run. So if we go and define an AC function that is called timeout with a delay seconds, and this is basically the same code that we have here, but instead of calling resolve, we are calling reject after some seconds. And we go on timeout after one second. I'm sorry but this is formatting the code every time I say, but yeah, if I do a race between a timeout that will timeout after one second and the non-blocking function that takes two seconds to rerun, the timeout is going to win and it gets through the error path. If I invert the time so that it turns out that there are two seconds but the actual logic takes one second to complete, the logic wins and yeah, we don't get a timeout. So basically this is how timeouts are implemented and if you're, you know, the tool you're using doesn't let you define timeout in a nice way but it works with promises, you can use RACE for that. You can have timeouts in whatever process that is. And the last, the same pattern and I'm adding this just because it's there, it's available in promise. This, the any method here and this is basically the same thing. This is RACE but in this, in this case, the any will keep waiting like, whoops, if I have the timeout again, I'll copy it here and I timeout after one second, then I timeout after two seconds and then still this is going to be successfully executed. It will wait in case any of the promises gets resolved before, you know, rejecting the whole promise. So if I run that, yeah, in the background, the timeout started projecting that the promise, but since this worked, we are getting the three. And then yeah, this is very similar to our race here. And yeah, this is basically the contents I wanted to go through. We are done with contents and only seven minutes over the two hours max. So I'm really happy about it. Do you have, before we finish the workshop, do you have any questions for me, or maybe you can go and copy and paste some piece of code in the chat, we can analyze it together or something like that. Yeah, you're right Bjorn. Two minutes early, right? Really? Okay. You're welcome. Thank you all for coming I guess. I'm really glad that so many people joined, and yeah, 39 still there, so kudos. Thank you all for coming, really. I'm really glad that so many people stayed until the end, you're my heroes. And also if anybody has any question, anytime, I'm on Twitter, and you can reach me on Github too. That's my Twitter handle, just drop me a line. I will be very happy to answer or try to help you in any way I can. And again, I work at TSN Simple, we are a small team, we are looking for more people to join us, so be sure to check our jobs page if you are on the market. Why did you use the Promise syntax instead of async await? Oh, that's a really good question. Let's answer that. Cool, so async await is this thing that I'm using here. So, the deal is that if I use async before a function, I'm forced to return a promise. Like that function, I'm giving hints to the language. Okay, I'll answer that later, Khalil. We have a couple of questions already. This is great. So, I am required to return a promise now because I used async, right? So, what I get by doing this is that I can, well, this doesn't make much sense, but anyway, I can now wait for the non-blocking from whatever, let's start a new example because this is getting complicated, all right. Okay, so let's define a function, a synchronous function that is called, well, let's call it foo with some value and delay, and this is going to return a new promise that resolves with a setTimeout and returns the value, like it basically repeats the value that you provide after some delay, okay? So you can call foo with 42 after 1000 milliseconds, you get the value and this should console log 42, right? After one second, let's try this real quick. There you go, it's working right? So if since I used async here, what I can do instead of using this syntax here, I can actually assign the value of foo of calling foo. If I call foo within a wait in front of it, right, and this is not going to work. First I need to do some tweaks to it, this is going to complain because you can't use a wait in a function that is not async. Like this is our requirement. So I'm going to wrap everything in a function called run, that is async, okay. And then I'm going to call run for now. It always returns a promise regardless of the return value, the point wait for the result, not so when we're wrapping it with promise always. Oh yeah, thank you. I'm going to, yeah, I'm moving towards that. Yeah, first I need to establish the base. Like how this works, right? You need to wait and then you can assign any value you want.

Replacing Promise All and Load Balancer Usage

Short description:

And then what they are suggesting in the shot here is that I could basically replace the promise all call with a sequence of then calls. This syntax is much simpler and can be used if you don't need all operations to run at the same time. However, it's important to understand that this is not equivalent to the promise all call. Regarding using an application level load balancer like PM2 in production with Node, it depends on the specific problem you're trying to solve. If you're supporting a web application, the single-threaded model of Node.js fits well. However, for other scenarios with multiple processes, further exploration is needed. As for CPU-intensive jobs in Node, it requires careful analysis and instrumentation of your solution to determine if the problem is truly an inefficiency. There may be simpler problems or alternative approaches to consider.

And then what they are suggesting in the shot here is that I could basically why not just do something like value one, I would put value two. Oops, I'm content to a sorry. And value three, and this is I don't know, 41, 42, 43, for example. Right? And this is basically replacing the promise all, right? Because I'm effectively waiting for all the promises to be resolved. And if I run this, I should, well let's have a really quick delay so that we don't have to wait so much. Like this is getting us almost the same thing, right? It's not the same thing though, because this is running this, waiting for it to be completed. And then running this, waiting for it to be completed and then running this. And if these are three input output operations, we are not really letting the underlying operating system deal with them in the best way possible. Like we are not signaling our program to launch the three operations and waiting for all of them to be completed. Like this is not, this is not the equivalent to the promise all call. This would be equivalent to then, dot then, dot then, dot then in the sequence, right? That's the first difference we have. I don't know if you cannot wait for more than one thing, maybe there's a way of doing that like you would do in a promise all call anyway. And the way to deal with timeouts, I'm not sure, really. I haven't played around with this so much to give you a better explanation at this point, but yeah, I hope that this makes sense. This also is a much nicer syntax, I would argue, like using then and then, if you can model your program like that, it's really nice. And maybe you don't care about all these three operations running at the same time or managed by the operating system, maybe this is good enough for you. And then the syntax is much simpler, right? Yeah. Ba-do-ba-do.

Well, does this seem true? If toddler returns a promise or a return value, that points, yeah, there you go. What do you think about using some kind of application level load balancer like PM2 in production with Node, since it's single threaded? Do you think it's mandatory to get full benefits of the machine? I don't know, that really depends on your, yeah. I'm sorry, I'm answering, I don't know a lot. It's really about the specific problem you're trying to solve. I would argue that if, for example, you are just supporting a web application, the web engine, maybe it's engines or whatever it is, is going to spawn a thread for you. And this model of having just one thread and a queue really fits really well within that model of execution. If you are doing something else, then you need to explore other options. I haven't, I don't have experience working with multi, like, modeling nodeJS systems that have a lot of processes, you know, working at the same time and having, getting, yeah, that's a scenario that I haven't explored. Sorry, I can give you specific answers. And then Kadir, you also asked, how would you solve when you suddenly need CPU intensive job in Node? Well, I don't know. Sorry. Sorry, I don't know. This is really something that you need to, like, this is advanced stuff. You need to put a lot of attention in instrumenting your solution really well. Being able to analyze your program in turn so that you know that that is actually your problem. Maybe it's another problem you have, like, it's, we, and I'm sorry because you might have this program and you already might have researched it and you are certain about it, but I see how teams can rush into thinking that there is something, some inefficiency in there, like the root of some problem is some inefficiency and it turns out most of the time there is a simpler problem or maybe something that you can, yeah.

Okay, well, I hope that I answered your question somehow, is there any other question? Otherwise, I think you can call it a day. Thank you all for coming here again. And I guess I need to stop the recording or something else as the host. So, I'm going to do that. Thank you all for coming again, it was really, I was really happy to see so many people staying until the end. And yeah, enjoy the Congress, by the way.

Watch more workshops on topic

React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
Top Content
WorkshopFree
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.
Node Congress 2023Node Congress 2023
109 min
Node.js Masterclass
Top Content
Workshop
Have you ever struggled with designing and structuring your Node.js applications? Building applications that are well organised, testable and extendable is not always easy. It can often turn out to be a lot more complicated than you expect it to be. In this live event Matteo will show you how he builds Node.js applications from scratch. You’ll learn how he approaches application design, and the philosophies that he applies to create modular, maintainable and effective applications.

Level: intermediate
TestJS Summit - January, 2021TestJS Summit - January, 2021
173 min
Testing Web Applications Using Cypress
WorkshopFree
This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.
We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.
Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.
JSNation 2023JSNation 2023
104 min
Build and Deploy a Backend With Fastify & Platformatic
WorkshopFree
Platformatic allows you to rapidly develop GraphQL and REST APIs with minimal effort. The best part is that it also allows you to unleash the full potential of Node.js and Fastify whenever you need to. You can fully customise a Platformatic application by writing your own additional features and plugins. In the workshop, we’ll cover both our Open Source modules and our Cloud offering:- Platformatic OSS (open-source software) — Tools and libraries for rapidly building robust applications with Node.js (https://oss.platformatic.dev/).- Platformatic Cloud (currently in beta) — Our hosting platform that includes features such as preview apps, built-in metrics and integration with your Git flow (https://platformatic.dev/). 
In this workshop you'll learn how to develop APIs with Fastify and deploy them to the Platformatic Cloud.
Node Congress 2023Node Congress 2023
63 min
0 to Auth in an Hour Using NodeJS SDK
WorkshopFree
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool.
We will enhance a full-stack JS application (Node.JS backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session for subsequent client requests, validating / refreshing sessions
At the end of the workshop, we will also touch on another approach to code authentication using frontend Descope Flows (drag-and-drop workflows), while keeping only session validation in the backend. With this, we will also show how easy it is to enable biometrics and other passwordless authentication methods.
Table of contents- A quick intro to core authentication concepts- Coding- Why passwordless matters
Prerequisites- IDE for your choice- Node 18 or higher
JSNation Live 2021JSNation Live 2021
156 min
Building a Hyper Fast Web Server with Deno
WorkshopFree
Deno 1.9 introduced a new web server API that takes advantage of Hyper, a fast and correct HTTP implementation for Rust. Using this API instead of the std/http implementation increases performance and provides support for HTTP2. In this workshop, learn how to create a web server utilizing Hyper under the hood and boost the performance for your web apps.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
JavaScript in the browser runs many times faster than it did two decades ago. And that happened because the browser vendors spent that time working on intensive performance optimizations in their JavaScript engines.Because of this optimization work, JavaScript is now running in many places besides the browser. But there are still some environments where the JS engines can’t apply those optimizations in the right way to make things fast.We’re working to solve this, beginning a whole new wave of JavaScript optimization work. We’re improving JavaScript performance for entirely different environments, where different rules apply. And this is possible because of WebAssembly. In this talk, I'll explain how this all works and what's coming next.
React Summit 2023React Summit 2023
24 min
Debugging JS
Top Content
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.
Node Congress 2022Node Congress 2022
26 min
It's a Jungle Out There: What's Really Going on Inside Your Node_Modules Folder
Top Content
Do you know what’s really going on in your node_modules folder? Software supply chain attacks have exploded over the past 12 months and they’re only accelerating in 2022 and beyond. We’ll dive into examples of recent supply chain attacks and what concrete steps you can take to protect your team from this emerging threat.
You can check the slides for Feross' talk here.