Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine.

How to install

With installer

Brew

brew install node

What Node.js can do?

  • Web servers
  • Development tooling
  • Desktop apps
  • Command line tools
  • etc

Main concepts &

API Reference

console.log(global);

global.setTimeout(() => console.log('timeout'));
setTimeout(() => console.log('timeout'));

process // current process methods/properties

__filename // absolute path to current file

__dirname // absolute path to directory where the file is located

require() // module resolver
const redux = require('redux'); // import redux from 'redux';

module
exports
module.exports === exports;


ECMAScript modules (es6) status in Node is still experimental due to different implementation compare to commonJS. 

 

Right now ECMAScript modules could be used with babel or natively with experimental flag

npm install babel-cli babel-preset-env

babel-node index.js
# .babelrc

{
    "presets": [
        "env",
    ]
}
node --experimental-modules my-app.mjs

ECMAScript modules should have .mjs extension

 EventEmitter is the most important class in NodeJs which helps to use event-driven model. It used widely by both internal and external modules

Node.js core API is based on asynchronous event-driven architecture in which certain kind of objects called emitters periodically emit events that cause listener objects to be called.

const { EventEmitter } = require('events');

const emitter = new EventEmitter();

function someEventListener(...args) {
    console.log('some event: ', ...args)
}

emitter.on('SOME_EVENT', someEventListener);
emitter.emit('SOME_EVENT', 'some', 'arguments');

emitter.removeListener('SOME_EVENT', someEventListener);
emitter.emit('SOME_EVENT', 'some', 'arguments');
  • uncaughtException

  • unhandledRejection

  • exit
  • beforeExit
const { EventEmitter } = require('events');

console.log(process instanceof EventEmitter); // true
process.on('uncaughtException', (err) => {
    console.log(err);
    console.log('caught!');
});

throw 'ERRRRRRRROR!'
process.on('unhandledRejection', (err) => {
    console.log(err);
    console.log('Did you forget to attach a catch handler for your promise?')
});

Promise.reject();
process.on('beforeExit', () => {
    console.log('Let me exit pls');
    setTimeout(() => {
        console.log('nope');
    }, 0);
});
process.on('exit', () => {
    console.log('Process is about to exit!');
})

const start = Date.now();

while (Date.now() - start < 1000) {
    ;
}

Most asynchronous methods exposed by the Node.js core API follow an idiomatic pattern referred to as an error-first callback. With this pattern, a callback function is passed to the method as an argument. When the operation either completes or an error is raised, the callback function is called with the Error object (if any) passed as the first argument. If no error was raised, the first argument will be passed as null.

function errorFirstCallback(err, data) {
  if (err) {
    console.error('There was an error', err);
    return;
  }
  console.log(data);
}

Built-in modules

fs

The Node.js file system module allows you to work with the file system on your computer.

const fs = require('fs');
const path = require('path');

fs.readFile(__filename, 'utf-8', (err, file) => {
    if (err) {
        console.log('error: ', err);
        return
    }
    console.log(file);
});
const file = fs.readFileSync(__filename, 'utf-8');
console.log(file);

fs.writeFile(path.join(__dirname, './1.txt'), 'Hello\nWorld\n!', (err) => {
    if (err) {
        console.log('error: ', err);
        return
    }
    console.log('done!');
});

fs.readdir(__dirname, (err, dir) => {
    console.log(dir);
});

node.js process

input data stream 

output data stream

Streams are collections of data — just like arrays or strings. The difference is that streams might not be available all at once, and they don’t have to fit in memory. This makes streams really powerful when working with large amounts of data, or data that’s coming from an external source one chunk at a time.

const stream = require('stream');

class MyWritableStream extends stream.Writable {};
class MyTransformStream extends stream.Transform {};

const fs = require('fs');
const writable = fs.createWriteStream(__filename);
const readable = fs.createReadStream(__filename);

Stream could be:

  • Readable (fs, net, http, stdin)
  • Writable (fs, net, http, stdout)
  • Transform (zlib, crypto)
  • Duplex (net)

Schedules the "immediate" execution of the callback after I/O events' callbacks.


setTimeout(() => console.log('timeout'), 4);

setImmediate(() => console.log('immediate'));

console.log('sync');

// outputs "sync" then "immediate" then "timeout";

The process.nextTick() method adds the callback to the "next tick queue". Once the current turn of the event loop turn runs to completion, all callbacks currently in the next tick queue will be called.

console.log('sync');
setTimeout(() => console.log('timeout'), 4);
setImmediate(() => console.log('immediate'));
process.nextTick(() => console.log('next tick'));

// outputs "sync" then "next tick" then "immediate" then "timeout"

EventLoop and the big picture (original resource)

EventLoop and the big picture (original resource)

This entire process is governed by libuv

libuv is cross-platform support library which was originally written for NodeJS. It’s designed around the event-driven asynchronous I/O model.
The library provides much more than a simple abstraction over different I/O polling mechanisms: ‘handles’ and ‘streams’ provide a high level abstraction for sockets and other entities; cross-platform file I/O and threading functionality is also provided, amongst other things.

Nodejs introduction

By Nikita Rudy

Nodejs introduction

  • 597