Skip to main content

Getting started

Screencast channel

You can see all video playlist for Week 1 here: https://screenpal.com/channels/c0fvXlVYvi

Official development docs

You can visit NodeJS official learning material for a more complete guideline over NodeJS

Our recapitulated version

Prerequisites

In order to start with NodeJS, you must know how to code in Javascript already, if you have not, please make sure that you can at least take a look here to build a solid foundation.

As we were at the same position as you were, we spent hard time digging around the documentation to figure out how to actually learn NodeJS, much time wasted. So here we are here to make sure you can pick up NodeJs as fast as possible. Stay tuned!

info

Install Node.js 20.11.0 for the best compatibility. Use NVM for great ease of installing multiple versions.

Hello world

You can create your new project folder, create a new file called hello.js as below: hello.js

After that you have two ways to run this hello world snippet:

  • Using the command line: node nodejs/basic/hello.js
  • Using the Webstorm run: Right click (on the file) > Run, see this screenshot

Congratulation, you have run your first NodeJs Hello World 🍻🍻🍻

NodeJS basic syntax

NodeJs literally means that Server-side Javascript, you basically you are writing Javascript. If you know how to write Javascript, you can do the exact same thing on NodeJS (mostly alike ES6, except for the import/export syntax). Let's see some code in action.

Declare variables

/**
* You can declare variable with const, let, var
* But it is recommended to use const
*/
const myTechStack = ['NodeJs', 'ReactJs', 'Firebase']; // It is recommended that you use camelcase for variable name
// myTechStack = ['NodeJS'] //This will throw an error because you cannot change a constant

let myFirstStack = 'NodeJs';
// Well, with let or var, you change the variable
myFirstStack = 'React'; // Maybe your first stack can be React =)))

Functions

Official document on JS Functions can be found here

/**
* The function syntax is quite the same
* You can use both traditional function and the arrow function
*
* @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions
*/

function add(num1, num2) {
return num1 + num2;
}
console.log(add(1, 1));
const addArrow = (num1, num2) => num1 + num2 // Arrow function
console.log(add(1, 1))

High Order Functions

This is an quite easy-to-understand tutorial on Javascript High Order Functions

/**
* You can use the JS high order function in the NodeJS env
*
* See these guide on high order functions
* @link https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad
*/
const myTechStack = ['NodeJs', 'ReactJs', 'Firebase']; // It is recommended that you use camelcase for variable name
const myTechStatus = myTechStack.map(stack => {
return {
name: stack,
status: 'not-finished'
}
});
console.log(myTechStatus)

// Filter only unique item
const list = [11, 24, 31, 24, 11, 56, 34];
const onlyUnique = (value, index, self) => {
return self.indexOf(value) === index;
}
const filterList = list.filter(onlyUnique);
console.log(filterList);

Important ES6 features to know

Destructuring Assignment

/**
* Destructuring Assignment
* @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
*/

const getUser = () => {
// Mimic the process that we may retrieved the user data from the web somewhere
const user = {
id: 1,
name: "John Doe",
status: 'active'
};
// return the user object
return user;
};

const {name, status} = getUser(); // You can use DA to extract only needed info
console.log(name, status);

const logInfo = ({name, age = 19}) => { // default argument with age = 19
console.log(`Hi, I'm ${name}. I'm ${age}`);
};
// With destruction parameter, you can swap the parameters order as you like
console.log(logInfo({age: 19, name: "John Doe"}));

Spread/Rest operator

The most common usage of the feature is to merge two object. You can see the snippet to understand and pull the most out of this feature:

/**
* Merge two object with spread syntax
*https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
*/
const person = {
id: 1,
name: "John Doe",
};

const job = {job: 'NodeJs Developer'};
const mergePerson = {...person, ...job};
console.log(mergePerson);

// You can use this to pick/omit fields from object
const post = {
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
};

const {userId, id, ...postSelected} = post; // post object should contain only title and body
console.log(post);

Async Programming

Async programming greatness!

One of the greatest feature of Javascript/NodeJS is Asynchronous Programming, which means that you don't need to do execute every action step by step, but do many actions at once at save time.

You can see this article for further explanation on Async Programming

Please see the difference between these two snippets to quickly understand the good nature of the async programming:

const delay = ms => new Promise(res => setTimeout(res, ms));

const promise1 = async () => {
await delay(1000);
console.log("Promise 1 executed")
};

const promise2 = async () => {
await delay(3000)
console.log("Promise 2 executed")
};

// Consider this to be a controller
(async () => {
try {
const start = new Date();
await promise1();
await promise2()
const end = new Date() - start
console.info('Execution time: %dms', end) // This will take 4s
} catch (e){
console.log("Got an error here")
}
})();

const delay = ms => new Promise(res => setTimeout(res, ms));

const promise1 = async () => {
await delay(1000);
console.log("Promise 1 executed")
};

const promise2 = async () => {
await delay(3000)
console.log("Promise 2 executed")
};

// Consider this to be a controller
(async () => {
try {
const start = new Date();
await Promise.all([
promise1(),
promise2()
]);
const end = new Date() - start
console.info('Execution time: %dms', end) // This will take 3s only
} catch (e){
console.log("Got an error here")
}
})();

Async/Await

You can see the this official document on how to use async/await syntax

If you don't like the Official documentation, you can keep up with our documentation, which will also give you complete view of Asynchronous Programming with NodeJs. In order to perform Asynchronous Programming, we have three methods:

  • Callbacks
  • Promise
  • Async/Await

Okay, let dive in the code!

Asynchronous programming with callback

/**
* Here is a glimpse into how async programming used to work with callback
*
* @param callback
*/
function getData(callback) {
setTimeout(() => {
const data = [
{id: 1, name: "Developer A"},
{id: 2, name: "Devloper B"}
]; // Assume the data from API

callback(data);
}, 1000)
}

getData((data) => {
const names = data.map(data => data.name);
console.log(names);
});

Callback hell

/**
* @description This is a example with 3 layer callback hell
*/

/**
* Fake like we getting data from API which takes 1s
*
* @param callback
*/
function getData(callback) {
setTimeout(() => {
const data = [
{id: 1, name: "Developer A"},
{id: 2, name: "Devloper B"}
]; // Assume the data from API

callback(data);
}, 1000)
};

/**
* Fake like we are submitting the data to an API elsewhere
*
* @param inputData
* @param callback
*/
function submitData (inputData, callback) {
console.log('starting to submit');
setTimeout(() => {
// Act like we submit the inputData to the server and takes 1s
const status = randomStatus();
callback({
success: status
});
}, 1000)
}

/**
* Just a helper random the result of the submit: success or failed
*
* @returns {boolean}
*/
const randomStatus = () => [true, false][Math.floor(Math.random() * 2)];

// Main body of the example
getData((data) => {
const names = data.map(data => data.name);
console.log(names)
submitData(names, (response) => {
const {success} = response;
if (success === true) {
console.log("This is a successful form")
} else {
console.log("This is a failed form")
}
})
});

/**
* @conclusion
*
* Just imagine that after submit the form,
* we continue to do more async processes
* and the code keeps on being nested
*
* @see See this link for closer look at callback hell
* @link http://callbackhell.com/
*
*/

Asynchronous Programming with Promise

/**
* Asynchronous programming with Promise
*/
function getData() {
return new Promise((resolve, reject) => {
const data = [
{id: 1, name: "Developer A"},
{id: 2, name: "Devloper B"}
];

setTimeout(() => {
resolve(data);
}, 1000);
});
}

/**
* Fake like we are submitting the data to an API elsewhere
*
* @param inputData
*/
function submitData (inputData) {
console.log('starting to submit');

return new Promise((resolve, reject) => {
// Act like we submit the inputData to the server and takes 1s
const status = randomStatus();

setTimeout(() => {
resolve({
success: status
});
}, 1000);
});
}

/**
* Just a helper random the result of the submit: success or failed
*
* @returns {boolean}
*/
const randomStatus = () => [true, false][Math.floor(Math.random() * 2)];

// Main body of the example
getData().then(data => {
const names = data.map(data => data.name);
console.log(names);
submitData(names).then(response => {
const {success} = response;
if (success === true) {
console.log("This is a successful form")
} else {
console.log("This is a failed form")
}
});
});

You can see that Promise can also become Promise Hell since the code keeps on being nested over time

Async/Await Syntax

/**
* Asynchronous programming with Promise
*/
function getData() {
return new Promise((resolve, reject) => {
const data = [
{id: 1, name: "Developer A"},
{id: 2, name: "Devloper B"}
];

setTimeout(() => {
resolve(data);
}, 1000);
});
}

/**
* Fake like we are submitting the data to an API elsewhere
*
* @param inputData
*/
function submitData (inputData) {
console.log('starting to submit');

return new Promise((resolve, reject) => {
// Act like we submit the inputData to the server and takes 1s
const status = randomStatus();

setTimeout(() => {
resolve({
success: status
});
}, 1000);
});
}

/**
* Just a helper random the result of the submit: success or failed
*
* @returns {boolean}
*/
const randomStatus = () => [true, false][Math.floor(Math.random() * 2)];

// Main body of the example
(async () => {
const data = await getData();
const names = data.map(data => data.name);
console.log(names);
const {success} = await submitData(names);
if (success === true) {
console.log("This is a successful form")
} else {
console.log("This is a failed form")
}
})();

You can see this video for better understanding:

note

As you can see, the code seems much cleaner with Async/Await syntax. Happy coding! That is it! You have take a look through some very key note features/syntax of NodeJS. Next, you will have some exercise to practice your newly-acquired skills.

Further dive (recommend only)

If you have more free time on your own, you should spend your time reading on your own understanding basic of Javascript to gain solid foundation for your programming skills:

Read Javascript from notice to ninja

Speaking from personal experience training many members, I recognized that trainee seems to miss much foundation knowledge of the programming:

  • Basic computer science, computer structure and models.
  • Computer operating system: Linux, Windows, CLI commands for Linux
  • Basic networking: IP, Server-Client model, Internet connection.
  • Advanced programming notions: OOP, Functional Programming
  • JS advanced: currying, closures, IFFY, Exceptional Handling, prototype, DOM, Dev tools