Did somebody say it was already Friday? Blimey now I understand why the acronym "TGIF" exists. But yet again, another brilliant but definitely exhausting week at the Northcoders Bootcamp!
Good morning, good afternoon and perhaps good evening, and a huge thank you again for coming to check up on me and my journey here at Northcoders
As always, feel free to drop me a follow on Twitter, LinkedIn and GitHub!
So... How has the fifth week treated me?
Perhaps if you have read my previous week's post of comparing how it went to trying to catching a plane that just set off, just imagine that you're stuck in the ocean as the plane that you're trying to catch off has already set off a few hours ago. Yep, that's how I felt this week π
The beautiful thing about the structure of Northcoders is that each topic that we learn builds off of concepts that we had covered beforehand. And before you even realise it, you've already learnt so much compared to where you first started!
I mean in all honesty, if I showed myself the code I had written in Express to the past me that had just started Northcoders, I would be skeptical and even ask myself "Where did you copy and paste that code?"
So to fellow Northcoders who may feel like they have struggled with this week's concepts and perhaps feeling behind, please don't put yourself down and instead look back at what you have done so far and be as proud as I am at your own progress.
In order to run we must first walk, and everyone will start walking and running at different times, your time will come!
With that said, this week felt significantly more difficult because previously we were dealing with the "Fundamentals" per the name of the block.
Where we were mostly gaining an understanding of the data types and the intricacies of how they worked because all of this indefinitely feeds into the rest of the course (Backend/Frontend).
What I Struggled Most With
This week I feel like I struggled when we were thrown into the deep end and were told to learn a new library called Inquirer.js and to use the concepts we had learned to implement the library.
I won't sugarcoat it and say that I felt panicked but ultimately was able to take it one step a a time by:
- Reading the overview and understanding what the library was and why it was used
- Examples of how the library is used and breaking down what syntax is used for what purpose
- Reading the documentation on how individual methods in the library work
- Breaking down the task from Northcoders and using the library with the concepts covered.
I had the head mentor Christian drop in to see how I was doing and he kindly reassured me that what I felt was normal and was a hurdle everyone has to overcome because once we head to the final projects phase, we would have to learn entirely new technologies.
A huge shout out to all of the mentors that spent this entire week with scheduled periodic drop-ins and keeping us grounded by empathising with our own experiences, you're all exceptionally wonderful!
(P.s. A huge welcome to Mitch as a new addition to the Northcoders team!)
So, what did we cover this week?
This week we built on our understanding of callbacks, asynchronosity and asynchronous functions with the following topics of:
- Promises & Promise.all
- Creating a HTTP Server With Node's
createServer()
- Introduction to Express and Middleware
- The Concept of MVC - Model View Controller
- Introduction to SQL
Introduction to Promises
Promises... I promise you that I struggled with this π
So, what are promises? A "Promise" is simply an object in JavaScript that is used for asynchronous computation and it represents a placeholder for an asynchronousoperation that has not yet been completed.
A promise has the three possible states of:
- Pending - This is when the promise has not yet been fulfilled.
- Fulfilled - This is when the operations have been a success.
- Rejected - This is when the operations have been a failure.
In order to "fulfill" or "reject" a promise, we must use the methods of .then()
to describe what exactly will happen if the promise is successfully fulfilled, and a .catch()
method for unsucessful operations that rejects the promise.
Although this may look strange to those of you who may be unfamiliar with promises, please bare with me:
promise
.then((response) => {
// handle success
console.log(response);
})
.catch((error) => {
// handle error
console.log(error);
});
The chaining of .then()
followed by the .catch()
is only possible because a "Promise" is an object that has the methods (Functions) that are inherited by each new instance of a promise.
Therefore, simply accessing the methods with dot notation and adding a callback function will allow us to add computations upon fulfillment/rejection of the promise.
Promise.all()
I admit that I am one of the guilty Northcoderians that thought it was somewhat therapeutic to chain .then()
all over the screen π
So what exactly is this method and what does it do? Simply put, it will take in all of the pending promises, store them in a single array and with a single .then()
and .catch()
block will resolve all of the promises in one.
If a single promise within the Promise.all()
fails then it will automatically go straight into the .catch()
block, and is definitely something I struggled to fully comprehend.
But alas, the concept of Promise.all()
is something that is something that will eventually click once you finally hit a bottleneck of having many promises that needs to be resolved all in one location.
Here's an example that I will briefly just like to highlight how useful the Promise.all()
method was and how that helped somewhat shine the light on how to use it:
const fetchAllPets = () => {
return fs.readdir('./data/pets').then((pets) => {
const allPetsData = pets.map((pet) => {
return fs.readFile(`./data/pets/${pet}`, 'utf-8')
})
return Promise.all(allPetsData);
}).then((pets) => {
const parsedPets = pets.map((stringifiedPets) => {
return JSON.parse(stringifiedPets);
});
return parsedPets
})
So this was an example of a function that me and my pair had wrote for one of the sprints this week.
For this example, "fs" which stands for node's "File System" is a module that is used to get access to the local file system and do something with them.
We are using the "promises" version that requires you to resolve the promise before data is sent back.
But the most important part here is that when we define a new variabled called allPetsData
which maps over the array of data that we get back from reading the directory ./data/pets
is that this within itself is an array of around 13 pending promises.
Imagine if we had tried to resolve this individually, and how many lines of code we would need to use! Instead we just return all of the promises into an array that we then later use for further computation, such an elegant and clean way of doing things!
Creating HTTP Servers With .createServer()
Last week I touched upon HTTP methods, CRUD operations and the anatomy of a URL.
This time we were put to the test by using Node's module called HTTP that allows us to effectively create our own server running on the localhost on the port of our choice!
First we would have to require in the HTTP module, create a "server" variable that invokes this HTTP module with a callback, and finally to have the server listen to a port on our machine so that it can pick up requests.
const http = require('http')
const fs = require('fs')
const fsPromises = require('fs/promises')
const server = http.createServer((req, res) => {
//
}
server.listen(9090, (err) => {
if(err) console.log(err);
else console.log('Successful connection on port 9090');
})
With this setup, we can now deep dive into a bit of the anatomy in the example above:
- The
const server
is just the invocation of thecreateServer
method on thehttp
object that we had required in. - This
createServer()
method takes in a callback that has the "Req/Request" and "Res/Response" as its arguments. - The "Request" is an object that the server receives when a client user makes a "method" request to our server and its endpoints.
- The "Response" is also an object but this is what we use to send data over to the user.
Writing Responses Guideline
I believe that this small section is important because being able to successfully send a response back to the user is paramount to both the server and its users, so try and remember the following:
- A response will always require a "body" of information that will be sent back to the user.
- The response body will need to be of a string data type.
- It's recommended that you include a "Header" in your response - this contains metadata that will be sent back to the user pertaining to the response made.
Introduction to Express
A quick recap as to what a "parametric endpoint" is - it's simply a path that has a placeholder that is dictated by what the client puts.
E.g. https://northcoders.com/api/users/:userId
When we created our own servers with the HTTP.createServer()
module, we would have to do really ugly computation in order to deal with parametric endpoints.
Here's an example of how messy it can look when we had to deal with a parametric endpoint that ends with a digit.
if (/\d+$/g.test(req.url) && req.method === "GET") {
//
}
Not exactly the easiest code to understand and it can definitely lead to a lot of confusions, but with the minimalistic backend framework of Express.js, our lives are somewhat a little bit easier!
Express is described as a minimalistic framework because it allows us to concentrate on dealing with the requests coming in and serving up responses to the enduser.
With Express we had access to a wide variety of tools such as:
- Req.params - This is what we will be using to deal with dynamic parametric endpoints, no more Regex conditionals.
- Req.query - This is what we will be using to get access to the queries being parsed in the request by the client.
-
Res.send()
- This is the method we invoke with a string of data to be sent back to the user. -
Res.status()
- This is the method that we can append to the response being sent back to the user that will contain the status code depending on the HTTP method and if it was successful or not.
I could go on all day about how relieving it was to go from Node's HTTP Module to Express and its features, but I'll save that for another day!
Introduction to the MVC Architecture
The MVC Architecture simply stands for "Model View Controller" and is a simple way of setting up your backend server so that each individual component is responsible for its own functionality.
And as such the functionalities are:
- Model - This will deal with data in storage - whether this is reading/writing/updating/deleting data locally or on a database.
- View - This is what will be sent back to the user in the form of a HTML file and corresponding CSS/JS files when the server is finished rendering.
- Controller - This will handle the requests & responses, and as such is classed as the "Middleware Function". The controller is responsible for taking in requests, sending instructions to the model to retrieve data and send it back to the user.
Previously myself and my pair were bewildered at the concept and questioned why such a concept existed, in which the answer lied in "structure" and "scalability".
Sure, we would be able to create an entire server in one file that handled all three, but if we ever wanted to scale p and perhaps change the "model" that handles the data, then this would be difficult because there would be an infinite amount of code to filter through just to find data pertaining to that model.
Although it makes sense, refactoring it into the MVC Architectural model definitely took a bit of time to get used to and understand!
SQL - My Dreaded Enemy
For so many years I have avoided SQL because of its very nature that just absolutely scared me. But after spending an entire day trying to get to grips with it, I can say that it is something I will need to spend more time with π
So, what is SQL? SQL stands for "Structured Query Language" that is based on "relational databases", this means that it has columns and rows of data for each table in a single database, and you're able to "relate" data between tables by doing pretty neat things such as "joining" them together and creating an entirely new table by using data from multiple tables.
Beyond this I could try and explain the complete intracies of the language but then I'd end up writing the documentation, so just know that it's a logically structured language that is useful when making complex queries!
Thoughts Going Forward
I believe that after having talked with Scarlett (one of our great mentors) that we don't have to mess around too much with vanilla SQL with the introduction to "Node-postgres" that has made me feel more at ease and so I'm just ready to enjoy my weekend, and I hope you all are too!
Honestly that's about it for this week's blog, but if you have gotten this far then thank you again for taking the time to read and I will see you next week!
Socials
Feel free to give me a follow on any of my socials down below!
Top comments (0)