An overview of JavaScript and Node.js

Luciano Mammino (@loige)

June 24, 2020

University Webinar Series

👋 Hello, I am Luciano!

Principal Software Engineer at FabFitFun

 Blog: loige.co

 Twitter: @loige

 GitHub: @lmammino 

let's connect!

👨🏻‍🏫 Mentor and co-organizer at NodeSchool Dublin

Agenda

  • What is JavaScript
  • JavaScript strengths
  • What is Node.js
  • Learning Resources
  • Q&A

What is JavaScript

JavaScript is an high-level, interpreted, multi-paradigm, dynamic & loosely-typed programming language

High-level: the language abstracts many system details (e.g. memory management).

 

Focus on productivity rather than control.

int *array = malloc(10 * sizeof(int));
if (array == NULL) {
  fprintf(stderr, "malloc failed\n");
  return -1;
}
// ...
free(array);
var arr = []

C (low-level)

JavaScript (high-level)

Interpreted: the source code can be executed directly using an interpreter (there is no compilation step).

 

Focus on portability and productivity rather than performance

javac HelloWorld.java
java HelloWorld.class
node hello-world.js

Java (compile)

JavaScript (intepreted)

Multi-paradigm: the language supports multiple programming paradigms:

  • Functional
  • Object-oriented (through prototypal inheritance)

 

Focus on flexibility and freedom rather than consistency

dynamic: the type of variables does not need to be defined.

loosely typed: the type of variables can change over time and different types of variables can be combined (through auto-casting)

Focus on productivity rather than safety.

2
 Advanced issues found
 
a = "Hello"
a = 2
b = "Hello" + 2 # TypeError!
var a = "Hello"
a = 2
var b = 'Hello' + 2 // 'Hello2'

python (dynamic, strongly typed)

JavaScript (dynamic, loosely typed)

Brendan Eich

(in a suit!)

JavaScript was created in 1995 by Brendan Eich to be the scripting language for the Netscape browser.

 

The name JavaScript comes by the fact that Netscape wanted the language to look similar to Java! (1)

 

In 1997 the language specification was standardized and called EcmaScript. (2)

In the last two decades, JavaScript has effectively revolutionized the web, eventually becoming the standard "de facto" for building dynamic websites and web applications!

JavaScript strengths

  • Async I/O
  • Ecosystem
  • Universal / Isomorphic web development

Async I/O

In JavaScript, input/output operations (e.g. making an HTTP request) are non-blocking.

Most languages have blocking I/O by default

Let's make an HTTP request in Java

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

.

Output

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

.

Output

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

.

Output

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

.

Output

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

.

Output

(Blocking I/O)

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

<google home page HTML code>

Output

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

<google home page HTML code>

Request completed

Output

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
  .url("https://google.com")
  .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
System.out.println("Request completed");

<google home page HTML code>

Request completed

Output

Code executed

"in order"

Is blocking I/O bad?

Is blocking I/O bad?

(it depends...)

Is your application I/O heavy?

Is your application I/O heavy?

If yes, then blocking I/O might not be optimal!

If you have to do 3 requests...

If you have to do 3 requests...

Req 1

time

If you have to do 3 requests...

Req 1

time

If you have to do 3 requests...

Req 1

time

Req 2

If you have to do 3 requests...

Req 1

time

Req 2

If you have to do 3 requests...

Req 1

time

Req 2

Req 3

If you have to do 3 requests...

Req 1

time

Req 2

Req 3

You can always use threads...

thread 1

time

thread 2

thread 3

You can always use threads...

thread 1

time

thread 2

thread 3

You can always use threads...

thread 1

time

thread 2

thread 3

But threads are...

 

You can always use threads...

thread 1

time

thread 2

thread 3

But threads are...

Complicated

You can always use threads...

thread 1

time

thread 2

thread 3

But threads are...

Complicated

Expensive

You can always use threads...

thread 1

time

thread 2

thread 3

But threads are...

Complicated

Expensive

Still a lot of idle time per thread!

You can always use threads...

thread 1

time

thread 2

thread 3

idle time

idle time

idle time

But threads are...

Complicated

Expensive

Still a lot of idle time per thread!

Let's understand JavaScript async I/O with a similar example...

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')
request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

.

Output

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

.

Output

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

.

Output

request "in the background"

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

Output

request "in the background"

not blocking,

execution continues...

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

Output

request "in the background"

not really completed, still in progress!

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

Output

request completed ⏰

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

Output

request completed ⏰

Callback function

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

<google home page HTML code>

Output

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

<google home page HTML code>

Output

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

<google home page HTML code>

Output

⚠️ Code NOT executed "in order"

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

<google home page HTML code>

Output

⚠️ Code NOT executed "in order"

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

<google home page HTML code>

Output

⚠️ Code NOT executed "in order"

request.get('https://google.com').end(
  (err, resp) => {
    console.log(resp.text)
  }
)

console.log('Request completed (?)')

Request completed (?)

<google home page HTML code>

Output

⚠️ Code NOT executed "in order"

When is this approach convenient?

When is this approach convenient?

For I/O heavy applications

When is this approach convenient?

For I/O heavy applications

JavaScript was built for the Browser, which is I/O heavy!

But why?

But why?

You just have to schedule async I/O and you will get notified when the operation is completed!

But why?

You just have to schedule async I/O and you will get notified when the operation is completed!

No explicit thread creation!

In fact, the "user" code runs in a single thread!

How?

How?

Thanks to the event loop!

How?

Thanks to the event loop!

It executes I/O efficiently in the background

If you have to do 3 requests...

If you have to do 3 requests...

"user" thread

time

Event loop

If you have to do 3 requests...

"user" thread

time

Sched. req 1

Event loop

If you have to do 3 requests...

"user" thread

time

Sched. req 1

Event loop

If you have to do 3 requests...

"user" thread

time

Event loop

Sched. req 2

If you have to do 3 requests...

"user" thread

time

Event loop

Sched. req 2

If you have to do 3 requests...

"user" thread

time

Event loop

Sched. req 3

If you have to do 3 requests...

"user" thread

time

Event loop

Sched. req 3

If you have to do 3 requests...

"user" thread

time

Event loop

idle

If you have to do 3 requests...

"user" thread

time

Event loop

idle

req 1 result

If you have to do 3 requests...

"user" thread

time

Event loop

idle

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

req 3 result

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

idle

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

idle

req 2 result

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

idle

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

idle

Simpler code for the user
 

If you have to do 3 requests...

"user" thread

time

Event loop

idle

idle

idle

Simpler code for the user
idle time only in one thread

This was a gross simplification...

Watch loige.link/event-loop-what-the-heck

if you want to go more in depth!

Since async is so fundamental there are many abstractions to handle async flow:

  • callbacks
  • promises
  • async/await
  • events
  • streams
  • async generators!

Ecosystem

The JavaScript community is one of the most active open source communities!

 

  • npm is the biggest repository of modules (1)
  • More than 1.25 bln modules and growing! (2)
  • There are modules for the most common needs (3)

Universal / Isomorphic web development

If you use JavaScript & Node.js you can build full stack web applications (frontend + backend) using only one language!

  • Less context-switching
  • Less time spent learning
  • Opportunity to share code between frontend & backend

Bonus:
Javascript is one of the fastest scripting languages

⚠️ WARNING
JavaScript is a pragmatic and beautiful language, but like everything, it's far from perfect and it has many quirks...

JavaScript WAT, a short talk by Gary Bernhardt
loige.link/js-wat

Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside a web browser.

What is Node.js

Created and launched in 2009 by Ryan Dahl to have a way to run JavaScript code outside a browser.

npm was launched in the same year.

 

Big companies (Linkedin, Uber, Paypal, Walmart) adopt Node.js early on.

 

In 2015 the Node.js foundation (now OpenJS) is born. (1)

Ryan Dahl
(in a T-shirt!)

Node.js differences

  • Does not run in the browser
    • No access to DOM and many other browser-specific APIs
  • It is not sandboxed as the browser
    • Can interact with the underlying OS (file system, network, syscalls, etc.)
  • Can have bindings to native code (N-API interface)

Node.js + JavaScript, when?

Node.js + JavaScript, when not?

  • You don't like the async model
  • You need fine-grained control on memory
  • You have to rely heavily on CPU/GPU rather than I/O
  • You prefer to release native (compiled) applications

Want to learn more?

THANKS! 

Thanks to @gbinside, @StefanoAbalsamo, @PadraigOBrien, @mariocasciaro & @hernandezlobera
for reviews and feedback!

An overview of JavaScript and Node.js

By Luciano Mammino

An overview of JavaScript and Node.js

In this talk, we will discuss JavaScript. Why does JavaScript exist in the first place? What is it useful for? How is it different from other mainstream languages like Java, Python or C? When you should consider using JavaScript (and when you shouldn't). We will also explore JavaScript server-side: Node.js and finally we will discuss when to use JavaScript + Node.js and when not to!

  • 312
Loading comments...

More from Luciano Mammino