Node.js introduction and installation

Node is a server running environment for JavaScript.

The “runtime environment” has two meanings. First, the JavaScript language runs on the server through Node, which is a bit like a JavaScript virtual machine in this sense. Second, Node is a JavaScript library in the sense that it provides a number of libraries that allow the JavaScript language to interact with the operating system (such as reading and writing files and creating child processes).

Node uses Google’s V8 engine as the JavaScript language interpreter. Call operating system resources through the self-developed Libuv library.

The website address

Download LTS version

use

Once installed, run the Node.js program to read the JavaScript script using the Node command.

The demo.js script file in the current directory can be executed as follows.

$node demo # or $node demo.jsCopy the code

With the -e argument, you can execute code strings.

$ node -e 'console.log("Hello World")'
Hello World
Copy the code

Type the node command on the command line with no file name, and you enter a Node.js REPL environment (Read – eval – print loop, Read – evaluate – print loop) that allows you to run various JavaScript commands directly.

$ node
> 1+1
2
>
Copy the code

REPL is the shell for Node.js to interact with the user, where basic shell functions can be used, such as using up and down arrow keys to iterate through previously used commands.

The special variable underscore (_) represents the result returned from the previous command.

> 1 + 1
2
> _ + 1
3
Copy the code

In the REPL, if you run an expression, the result is returned directly from the command line. If you run a statement, there is no output because the statement returns no value.

> x = 1
1
> var x = 1
Copy the code

Command line script

The Node script can be used as a command-line script.

$ node foo.js
Copy the code

The above code executes the foo.js script file.

The first line of the foo.js file, if the interpreter location is added, can be called directly as a command line tool.

#! /usr/bin/env nodeCopy the code

Before calling, you need to change the execution permission of the file.

$ chmod u+x foo.js
$ ./foo.js arg1 arg2 ...
Copy the code

When used as a command-line script, console.log is used to output content to standard output, process.stdin is used to read standard input, and child_process.exec() is used to execute a shell command.

Asynchronous operations

Node uses the V8 engine to process JavaScript scripts. The main feature of Node is that it is single-threaded and can only run one task at a time. This results in a large number of Asynchronous operations, in which tasks are not executed immediately but are inserted at the end of the task queue until the previous task is finished.

Because of this nature, subsequent operations on a task are often defined as callback functions.

var isTrue = function(value, callback) {
  if (value === true) {
    callback(null, "Value was true.");
  }
  else {
    callback(new Error("Value is not true!"));
  }
}
Copy the code

This code leaves further processing to the callback function.

The Node convention says that if a function requires a callback function as an argument, the callback function is the last argument. In addition, the first argument to the callback function itself, by convention, is the error object passed in from the previous step.

var callback = function (error, value) {
  if (error) {
    return console.log(error);
  }
  console.log(value);
}
Copy the code

If no error occurs, null is passed as the first argument to the callback function. One of the great advantages of this method is that you can tell if something has gone wrong by checking the first argument to the callback, and if it’s not null, it’s definitely wrong. In addition, this allows for layer upon layer transmission of errors.

Global objects and global variables

Node provides the following global objects that all modules can call.

  • Global: represents the global environment in which Node resides, similar to the window object of a browser. Note that if you declare a global variable in a browser, you are actually declaring a global object property. For example, var x = 1 is equivalent to setting window.x = 1. Global. X = undefined. This is because the global variables of a module are private to the module and cannot be fetched by other modules.
  • Process: This object represents the current process Node is in, allowing developers to interact with the process.
  • Console: refers to the built-in console module of a Node, which provides standard input and standard output functions in the CLI environment.

Node also provides some global functions.

  • SetTimeout () : Used to run the callback function after the specified millisecond. This method returns an integer representing the number of the new timer.
  • ClearTimeout () : Used to terminate a timer created by a setTimeout method.
  • SetInterval () : Used to call the callback function every certain millisecond. This method returns an integer representing the number of the new timer.
  • ClearInterval () : Terminates a timer created using the setInterval method.
  • Require () : Used to load modules.
  • Buffer() : Used to manipulate binary data.

Node provides two global variables, both beginning with two underscores.

  • __filename: indicates the filename of the currently running script.
  • __dirname: points to the directory of the currently running script.

In addition, there are some objects that are actually local variables inside modules, pointing to different objects according to different modules, but applicable to all modules, can be regarded as pseudo-global variables, mainly module, module.exports, exports, etc.

Modular construction

Preamble: Although NodeJS supports ES6 modularity, most of the packages use the CommonJS specification, so it is worth mentioning here

Node.js adopts a modular structure, defining and using modules according to the CommonJS specification. Module and file are one-to-one correspondence, that is, loading a module is actually loading a corresponding module file.

The require command is used to specify the module to be loaded. During the loading, you can omit the script file name extension.

var circle = require('./circle.js'); Var circle = require('./circle');Copy the code

The require method takes the name of the module file. There are two cases, one where the argument contains a file path (as in the example above) relative to the current script directory, and the other where the argument contains no file path and Node goes to the module’s installation directory to find the installed module (as in the example below).

var fs = require('fs');
Copy the code

Once a module is loaded, it is cached by the system. If the module is also loaded a second time, the version in the cache is returned, meaning that the module is actually executed only once. If you want the module to execute multiple times, you can have the module return a function and then call that function multiple times.

The core module

Simply running JavaScript code on the server is not very useful, as there are already many server scripting languages. Node.js is useful because it also provides a set of functional modules that interact with the operating system. The following is a list of these core functional modules that can be used without installation.

  • HTTP: provides the HTTP server function.
  • Url: Parses the URL.
  • Fs: interacts with the file system.
  • Querystring: querystring that parses the URL.
  • Child_process: Creates a child process.
  • Util: Provides a range of utility gadgets.
  • Path: indicates the path of processing files.
  • Crypto: Provides encryption and decryption capabilities and is basically a wrapper around OpenSSL.

Custom modules

Node modules adopt the CommonJS specification. You can customize modules as long as you conform to this specification.

Here is the simplest module. Suppose you create a new foo.js file and write the following.

module.exports = function(x) {
    console.log(x);
};
Copy the code

This code is a module that exports a method via the module.exports variable.

This module is used as follows.

// index.js var m = require('./foo'); M (" This is a custom module ");Copy the code

The code above loads the module file foo.js with the require command (the suffix is omitted), outputs the module’s external interface to the variable m, and then calls m. At this point, run index.js from the command line and the screen will say “this is a custom module”.

The module variable is the top-level variable of the entire module file, and its exports property is the interface that the module exports. If you output a function directly (like foo.js above), then calling a module is calling a function. However, a module can also output an object. Let’s rewrite foo.js.

// foo.js

var out = new Object();

function p(string) {
  console.log(string);
}

out.print = p;

module.exports = out;
Copy the code

The code above represents the module’s output out object, which has a print property pointing to a function. Here’s how to use this module.

// index.js var m = require('./foo'); M.int (" This is a custom module ");Copy the code

CommonJS specification

Node applications are composed of modules that follow the CommonJS module specification.

Each file is a module with its own scope. Variables, functions, and classes defined in one file are private and invisible to other files.

// example.js
var x = 5;
var addX = function (value) {
  return value + x;
};
Copy the code

In the above code, the variable x and function addX are private to the current example.js file, and not visible to other files.

If you want to share variables across multiple files, you must define them as properties of the Global object.

global.warning = true;
Copy the code

The warning variable of the above code can be read by all files. Of course, this is not recommended.

The CommonJS specification states that within each module, the module variable represents the current module. This variable is an object whose exports property (module.exports) is the interface to the outside world. Loading a module loads the module.exports property of that module.

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
Copy the code

The code above exports the x variable and the function addX via module.exports.

The require method is used to load modules.

var example = require('./example.js'); console.log(example.x); // 5 console.log(example.addX(1)); / / 6Copy the code

The CommonJS module has the following features.

All code runs in the module scope and does not pollute the global scope. Modules can be loaded multiple times, but only run once on the first load, and then the results are cached and read directly from the cache when they are loaded later. For the module to run again, the cache must be cleared. The order in which modules are loaded, in the order they appear in the code.

The module object

Node provides a Module builder function inside. All modules are instances of Module.

function Module(id, parent) {
  this.id = id;
  this.exports = {};
  this.parent = parent;
  // ...
Copy the code

Inside each module, there is a Module object that represents the current module. It has the following properties.

  • Module. id The module’s identifier, usually the module’s file name with an absolute path.
  • Module. filename specifies the filename of the module, with an absolute path.
  • Module. loaded Returns a Boolean value indicating whether the module has completed loading.
  • Module.parent returns an object representing the module that called the module.
  • Module. children returns an array representing other modules used by this module.
  • Module. exports indicates the value that the module exports.

Here is a sample file, with the last line printing the module variable.

// example.js
var fss = require('fs');
exports.fss = fss;
console.log(module);
Copy the code

When you execute this file, the command line displays the following information.

{
  id: '.',
  path: '/Users/luwnto/Desktop',
  exports: {
    fss: {
  ...  
  parent: null,
  filename: '/Users/luwnto/Desktop/a.js',
  ...
Copy the code

If a module, such as Node something-js, is called from the command line, module.parent is null. If it is called in a script, such as require(‘./ something-js ‘), then module.parent is the module that calls it.

The module exports attributes

The module.exports property represents the interface that the current module exports. Other files that load the module actually read the module.exports variable.

Exports variable

For convenience, Node provides an exports variable for each module, pointing to module.exports. This equates to a line of command in the header of each module.

var exports = module.exports;
Copy the code

As a result, methods can be added to exports objects when exporting module interfaces.

exports.area = function (r) {
  return Math.PI * r * r;
};

exports.circumference = function (r) {
  return 2 * Math.PI * r;
};
Copy the code

Note that you can’t point the exports variable directly to a value, because that breaks the link between exports and module.exports.

exports = function(x) {console.log(x)};
Copy the code

Exports no longer refers to module.exports.

The following is also invalid.

exports.hello = function() {
  return 'hello';
};

module.exports = 'Hello world';
Copy the code

The hello function cannot be exported because module.exports is reassigned.

This means that if a module’s external interface is a single value, it cannot use exports, only module.exports.

module.exports = function (x){ console.log(x); };Copy the code

If you find it hard to distinguish between exports and module.exports, a simple solution is to stop using exports and just use module.exports.

Exception handling

Node is a single-threaded environment that causes the entire process to crash if an exception is thrown that is not caught. Therefore, Node exception handling is very important to ensure the stable operation of the system.

Generally speaking, Node has three ways to propagate an error.

  • Use a throw statement to throw an error object, that is, an exception.
  • The error object is passed to the callback function, which is responsible for issuing the error.
  • Emits an error from the EventEmitter interface.

The try… Catch the structure

The most common way to catch an exception is to use a try… Structure of the catch. However, this structure does not catch exceptions thrown by code that runs asynchronously.

try {
  setTimeout(function(){
    throw new Error("error");
  },1000)
} catch (err) {
  //can not catch it
  console.log(err);
}
Copy the code

Cannot be caught by a catch block because the part of the catch block is already running.

One solution is to put error-catching code into asynchronous execution as well.

setTimeout(function() { try { if (true) throw new Error("woops!" ); else console.log("Ok"); } catch(e) { console.log(e); }}, 2000).Copy the code

Neither approach is ideal. In general, Node uses try/catch statements only in rare situations, such as parsing JSON text with json.parse.

The callback function

Node takes the approach of passing the error object as the first argument to the callback function. This avoids the problem of capturing code in a different time period from the code in which the error occurred.

fs.readFile('/foo.txt', function(err, data) { if (err ! == null) throw err; console.log(data); });Copy the code

The above code shows that reading foo. TXT is an asynchronous operation, and its callback takes two arguments, the first is the error object and the second is the data read from the file. If the first argument is not null, it means an error has occurred and the following code is no longer executed

EventEmitter Error event of an interface

The EventEmitter interface can also be used to throw error events when errors occur.

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();

emitter.emit('error', new Error('something bad happened'));
Copy the code

You must be careful with the code above, because if you do not deploy listeners for error events, the entire application will crash. As a result, the following code must generally be deployed at the same time.

Emitter. On ('error', function(err) {console.error(' error: '+ err.message); });Copy the code

Look forward to detailed tutorials