DEV Community

Cover image for The Rising Coder - Week 4/13 (Fundamentals Week 3/3)
Christopher Lam
Christopher Lam

Posted on

The Rising Coder - Week 4/13 (Fundamentals Week 3/3)

Christ, where has the time gone, it's already Friday and another end to a great week at the Northcoders Bootcamp!

Good morning, good afternoon or good evening and thank you as always for coming back to check out my journey at Northcoders - I hope you've all had a lovely week so far and an even better weekend coming up!

P.S. It's already been an entire month since myself and my fellow friends in the same cohort as mine have joined Northcoders, so a huge round of applause for us all, especially for the mentors and cohort members, you guys are absolutely a pleasure to get along with! 😁

As always, feel free to drop me a follow on Twitter, LinkedIn and GitHub!

Soooo... How has my fourth week been?

If you saw last week's post and how I thought it was like trying to catch a train that set off, this week felt like I was trying to catch a plane that just set off 😂

Imagine everything that you had learned previously about functions and how they are able to return a function or an invocation of a function as its value, and then told the next second that you just throw all of that away.

Because that was what we did this entire week! This entire week we focused on the ideas of "Asychronous Functions" and how they work, why we use them and why these will be our best friends for the rest of the Back-End!

But before that, I had mentioned that this week we would have a "Review Day" of the core fundamental concepts of: Array Methods, OOP, Recursion and Closure - and so that was what we did for the entirety of this Tuesday.

I am not going to sugarcoat it at all and be completely honest, the prospect of the review day had led me to become stressed and lose a few hours of sleep during the 3-day weekend.

But I am glad to say that I managed to survive and even receive lovely feedback from the mentors that were happy to say that my understanding of the concepts and my code were fantastic, which was one of the most relieving moments that I've had so far on the course!

List Of Topics Covered This Week

Besides surviving the review day, here's a quick bullet point of all of the concepts that we dove into this week:

  • Wednesday: Asynchronous Functions , making requests and the anatomy of a callback function in Node.
  • Thursday: Dealing with multiple asynchronous callbacks and dynamic requests to endpoints.
  • Friday: HTTPS, CRUD Methods, APIs & Endpoints.

As you can see from the sheer volume of topics above, these are all fundamental topics that we will be needing as we dive into the backend portion of the course, and as always I will try to provide a summary of what I have managed to learn coming out of this week!

Asynchronousity - Who, what, why and how?

The term "Asynchronous" essentially means being able to multi-task and do multiple things at once. For us Software Developers who use JavaScript - JavaScript is known as a single-threaded language, this means that it can only run through code one line at a time. Unlike other "multithreaded" languages such as C++.

This is important to note because we will be using Node.js which will allow us to implement the concept of "Asynchronosity" into JavaScript. Node.js is originally written for JavaScript to have asynchronous functionality, but in fact Node.js is actually written in C++, and so this is the reason that it is able to be multithreaded and handle more than one function at a time!

Understanding this, "Asynchronous Functions" are referred to as "facade functions" because although they look like a regular function, there is something really discerning about them that you will be able to immediately spot, and that is an asynchronous function does not return anything to the user.

Instead, the asynchronous function will return a "Callback" with any data it has and serve it to the user.

With Asynchronous Functions, although they may seem like regular functions, they are entirely different! When a regular function is created and invoked, it gets put on the "Call Stack" which will call "Global" on the call stack.

Asynchronous Functions on the other hand are only able to be put on the call stack when the call stack is empty. So if there are other regular functions on the call stack waiting to be popped off, then these asynchronous functions will be put in what is called the "Task Queue."

Depending on how long it takes for the asynchronous function to receive all of the data it needs will determine which item will first be popped from the task queue into the call stack.

But remember, that the asynchronous functions cannot be moved from the task queue into the call stack until it is empty! - This is where it's difficult to really visualise how long the task queue is, especially with multiple asynchronous functions being run simultaneously!

Making Requests & Node's Callback Function Anatomy

One of the most difficult things that myself and my pair-programming partner had to understand was the "Home-made Request Function" that Northcoders had created to simulate Node's Request function, and how callbacks are structured in Node when we create a callback.

For the home-made replicas of Node/Express' Request function, the anatomy is firstly the "Path" or "Endpoint" that we will be retrieving the data from, and then secondly will be the "Callback Function" that is used to execute the callback passed in as an argument, with the modified data.

Consider this example:

function fetchBannerContent(callback) {
  request('/banner', (err, contents) => {
    contents.copyrightYear = 2022;
    callback(err, { ...contents });
  });
}
Enter fullscreen mode Exit fullscreen mode

Here we have an asycnhronous function called fetchBannerContent that takes in a callback as its argument. The request will be making a request to the path/endpoint of '/banner', and then with a callback that takes an error and the contents that were fetched from the request being made to the endpoint of '/banner'.

In this case, the following object is received from the request:

{
  title: 'Kitty Litter',
  bannerImg: 'https://riotfest.org/wp-content/uploads/2017/10/AcT9YIL.jpg',
  copyrightYear: 2006
};
Enter fullscreen mode Exit fullscreen mode

Within this callback that has access to this data, we simply access the property of copyrightYear and change this from the original "2006" to "2022", and then invoke the original callback in the argument with the callback of (err, {...contents})

For those who have a keen eye, we had decided to create a new object (For a new reference in memory) and use the spread operator (ES6 "...") to copy those contents and then use this in the callback. And so the user wil receive the following object:

{
  title: 'Kitty Litter',
  bannerImg: 'https://riotfest.org/wp-content/uploads/2017/10/AcT9YIL.jpg',
  copyrightYear: 2022
};
Enter fullscreen mode Exit fullscreen mode

Multiple Asynchronous Functions & Dynamic Requests

If dealing with a single asynchronous function wasn't enough, try multiple asynchronous processes at the same time!

But first, the most beautiful things about ES6 and making "Dynamic Requests", is that you don't need to manually enter the path for the request.

function fetchCatsByOwner(owner, callback) {
  request(`/owners/${owner}/cats`, (err, cats) => {
    callback(err, cats);
  });
}
Enter fullscreen mode Exit fullscreen mode

Here we have a simple asynchronous function called fetchCatsByOwner that takes in an owner & callback as its arguments. The request body is where it is beautiful - by using template literals, we are able to put in the "Owner" as an argument and get back an array of cats that belongs to the owner that was passed in as the first argument when we invoke this function!

Perhaps that example was too simple because we would have to manually put in an "Owner". What if we wanted to fetch all of the cats from all of the owners?! Absolute madness!

function fetchAllCats(callback) {
  const catsArray = [];
  fetchAllOwners((err, owners) => {
    owners.forEach(owner => {
      fetchCatsByOwner(owner, (err, cats) => {
        catsArray.push(cats);
        if (catsArray.length === owners.length) {
          const flattenedCats = catsArray.flat().sort();
          callback(err, flattenedCats);
        }
      });
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

Here is a brief breakdown of what exactly is going on here, because it looks like complete chaos!

  • 1 - Firstly this function called fetchAllCats is designed to use a function called fetchAllOwners which will return an array of all of the owners. E.g. `['Chris', 'Daniel', 'Antony', 'Felicity', 'Benjamin', 'Kanti', 'Ikram', 'Christian', 'Alex'].
  • 2 - Secondly, through getting this array of owners - we are going to invoke the fetchCatsByOwner for each user in this array. (And as you can see in the previous example, as thanks to the dynamic route, we don't need to do it manually!)
  • 3 - Third, we push the array of cats that belongs to the owner for each personn in the "owners" array.
  • 4 - Fourth, once the length of the catsArray is equal to the owners array, we will flatten it and sort the cats array by alphabetical order.
  • 5 - Lastly, we invoke the original callback in the argument with (err, flattenedCats) and then this alphabetically ordered array of cat names will be served to the user. (PS Don't flatten your cats 😭)

Introduction HTTPS & CRUD Methods

I won't dive in too deep about the theory behind how the internet works, as this playlst will be a great reference point to how requests are made to servers and how we are able to retrieve data!

However, I will be talking a little about APis, endpoints and "CRUD Operations."

Firstly, APIs or "Application Program Interfaces" are servers that are able to provide raw text data to its users. (If you look for any random API and search for something, it will show you a completely blinding block of text - this is the raw data!)

Through this APIs, they have "endpoints" which just refer to the path that a user will be able to traverse to and get access to the data that exists on that path.

Below is a small explanation of the anatomy in an API:

Example: https://api.github.com/search/reports?page=2

  • https:// - This is the protocol that says how the data should be requested and responded to.
  • api - Nothing special but an indicator to users of what type of server they are accessing when entering.
  • github - this is the DNS provided address name.
  • .com - The top level domain that is often owned by countries or domain name providers.
  • search/repos/ - This is the "path" or "route" used by the precise document of where information si requested, known as the **endpoint**. Similar to how we are able to dynamically access an endpoint, we can use placeholders like /:placeholder/resource` to be dynamically based on the input from the user.
  • ?pages=2 - Often denoted by a question mark, the page and a number is a "query" that is being made to a server.
  • & - Using an and symbol, we can chain on other query terms that are available on an API.

As Software Developers these pieces of data that are served as raw text are invaluable to us because we are able to use this data to serve our own desires.

However, how do we get this raw text data into a more "Readable" format for us simple humans?

We will first need to use a method known as `JSON.stringify()' to convert the raw text data into a "JSON" format (JavaScript Object Notation), this will create a stringified object that looks akin to how objects are displayed in JavaScript.

Then we would use the function of JSON.parse() to take this object-looking string and then converts it into a JavaScript Object that we can comfortably use as Software Developers, it really is just that simple!

Lastly (I nearly had forgotten) are "CRUD Operations", and not the "crud" we say when we mess something up!

CRUD Operations stands for "Create, Read, Update and Delete", through certain HTTP methods we are able to:

  • Create new resources on a database
  • Read resources from a database
  • Update resources on a database
  • Delete resources on a database

And each of these HTTP methods are the following:

  • POST - This is the method used when we're trying to add something to a database. These requests will need to have a body of text/information that will be held and requested to be added to that database.
  • GET - This is the method used when we're trying to "get" or receive information back after we make a request.
  • PATCH/PUT - This is ued to partially update something in a database/resource.
  • DELETE - THis is the method that is used to delete a specific instance of a resource.

And that's about the gist for what we had learned this week! I could dive deep into the code written for todays's sprint but that would require an entirely new post! But fundamentally everything that we had learned this week was all of this!

Thoughts Going Forward

If you have made it this far to the end, thank you very much as always for checking in on me and my journey at Northcoders, it means the world to me!

I think for now I'm really ready to enjoy a well-deserved weekend and brace myself for the start of the "Backend" portion of the Northcoders Bootcamp - and I hope to see you all again next week!

Socials

Feel free to give me a follow on any of my socials down below!

Top comments (0)