Node.js is so popular that almost all front-end engineers want to learn it, and almost all back-end engineers want to learn it, too. When you think of Node.js, you might immediately think of “asynchronous,” “event-driven,” “non-blocking,” and “excellent performance,” but do you really understand what those words mean? This tutorial will give you a quick introduction to Node.js and give you a solid foundation for further front-end learning or node.js advancement.

This tutorial is part of the Node.js backend engineer learning path, welcome to Star wave, encourage us to continue to create better tutorials, update

start

What is Node?

Simply put, Node (or Node.js, which is equivalent) is a runtime environment for JavaScript. Before that, we knew that JavaScript was executed in the browser to add dynamic effects to web pages, so the browser was also the environment for JavaScript to run. So what are the differences between the two environments? See the picture below:

Both runtime environments include ECMAScript, the JavaScript language standard itself, stripped of all runtime environments. ECMAScript is growing at a phenomenal rate, almost one version per year.

prompt

The relationship between ECMAScript and JavaScript is that the former is a specification of the latter and the latter is an implementation of the former. In everyday situations, the two words are interchangeable. For more background, see Yifeng Ruan’s The History of the JavaScript Language.

On the other hand, browser-side JavaScript also includes:

  • The Browser Object Model, or BOM, iswindowobject
  • The Document Object Model (DOM), also known asdocumentobject

Node.js includes the V8 engine. V8 is the JavaScript engine in Chrome. After years of development and optimization, performance and security have reached a considerable height. Node.js takes the V8 engine one step further and turns it into a platform that can run JavaScript on any operating system.

Preliminary knowledge

Before you start this tutorial, we want you to be prepared:

  • Understand the basics of the JavaScript language, preferably with browser JS development experience
  • You’ve installed Node.js and configured your editor or IDE to suit you
  • Understand relative paths and absolute paths

Learning goals

This tutorial will teach you:

  • The relationship and difference between JavaScript and Node.js
  • Learn what global objects Node.js has
  • How does Node.js import and export modules, and how does the module mechanism work
  • Know how to develop simple command-line applications using Node.js
  • Learn to harness the power of the NPM community to solve development challenges and avoid “reinventing the wheel”
  • Understand the basic concepts and use of NPM Scripts
  • Get to know the event mechanism of Node.js

Run the Node code

There are usually two ways to run Node code: 1) interactively enter and run it in the REPL; 2) Write the code to a JS file and execute it with Node.

prompt

REPL stands for Read Eval Print Loop, and is generally understood as an interactive interpreter. You can type any expression or statement, and it will execute immediately and return the result. If you’ve ever used Python’s REPL, you’ll be familiar with it.

Quick experience with REPL

If you have Node installed, run the following command to print the node.js version:

V12.10.0 $node - vCopy the code

Then, we can also enter Node REPL (type Node directly) and type any valid JavaScript expression or statement:

$node Welcome to node.js v12.10.0.type".help" for more information.
> 1 + 2
3
> var x = 10;
undefined
> x + 20
30
> console.log('Hello World');
Hello World
undefined
Copy the code

Some lines start with >, which represents the input prompt, so the command we want to enter is followed by >, while others are the return value of the expression or Standard Output (stdout). The result is as follows:

Writing Node scripts

A REPL is often used to experiment with some code. When building a specific application, it’s more about creating Node files. We’ll start by creating the simplest node.js script file called timer.js with the following code:

console.log('Hello World! ');
Copy the code

Then execute the file with the Node interpreter:

$ node timer.js
Hello World!
Copy the code

It may seem pretty unremarkable, but this line of code is the work of the Node.js team. Let’s compare the difference between executing this line of code in a browser and Node:

  • Running in a browserconsole.logThe BOM is called, and what is actually done iswindow.console.log('Hello World! ')
  • Node first creates a new process on the operating system in which it is operating, and then prints the specified string to standard output, actually doingprocess.stdout.write('Hello World! \n')

In short, Node provides a browser-free environment for JavaScript code to run directly with the operating system!

Node global object exploration

If you’ve ever written JavaScript before, you’re no stranger to global objects. In the browser, we have global objects like document and window; Node only contains ECMAScript and V8, but does not contain BOM or DOM, so there is no document or window in Node. Instead, Node’s exclusive global object is Process. In this section, we’ll take a first look at Node global objects.

Classification of JavaScript global objects

Before we do that, let’s take a look at the comparison of global objects for each JavaScript runtime environment, as shown below:

As you can see, JavaScript global objects fall into four categories:

  1. Browser-specific, for examplewindow,alertAnd so on;
  2. Node exclusive, for exampleprocess,Buffer,__dirname,__filenameAnd so on;
  3. Browser and Node are shared, butDifferent implementations, e.g.console(as mentioned in section 1),setTimeout,setIntervalAnd so on;
  4. Browser and Node are shared and belong toECMAScript language definitionA part of, e.gDate,String,PromiseAnd so on;

Node is dedicated to global object resolution

process

The Process global object is the soul of Node.js. It is the object that manages the current Node.js process state and provides a simple interface to the operating system.

First let’s explore the important properties of the Process object. Open the Node REPL, and then look at some properties of the Process object:

  • pid: Process id
  • env: System environment variables
  • argv: Command line input parameter for executing the script
  • platform: Indicates the current operating system platform

prompt

Try these objects out in the Node REPL. Enter the REPL as mentioned above (your output will most likely be different from mine) :

$node Welcome to node.js v12.10.0.type".help" for more information.
> process.pid
3
> process.platform
'darwin'
Copy the code

Buffer

The Buffer global object makes it easy for JavaScript to handle binary data streams. Combined with Node’s Stream interface, it enables efficient binary file processing. Buffers will not be covered in this tutorial.

__filename__dirname

Respectively represents the file path and directory path of the Node script.

warning

__filename and __dirname are only used in Node script files and are not defined in the REPL.

Use Node global objects

Next we’ll use Node global objects in the script file we just wrote, covering each of the three categories:

  • The Node’s exclusive:process
  • Common global objects with different implementations:consolesetTimeout
  • Global objects defined by the ECMAScript language:Date

prompt

SetTimeout is used to execute specific logic after a certain amount of time. The first parameter is the function to execute when the time is up (the callback function), and the second parameter is the wait time. Such as:

setTimeout(someFunction, 1000);
Copy the code

The someFunction function is executed 1000 milliseconds later.

The code is as follows:

setTimeout((a)= > {
  console.log('Hello World! ');
}, 3000);

console.log('Current process ID', process.pid);
console.log('Current script path', __filename);

const time = new Date(a);console.log('Current time', time.toLocaleString());
Copy the code

Running the above script produces the following output on my machine (Hello World! Output will be delayed by three seconds) :

$node timer. Js current process ID 7310 current script path/Users/mRc/Tutorials/nodejs - quickstart/timer. Js 12/4/2019 current time, 9:49:28 AM Hello World!Copy the code

Node.js async is a good example of node.js async non-blocking when the setTimeout waits for 3 seconds and the program does not block.

prompt

In the actual application environment, there are often many I/O operations (such as network requests, database queries, etc.) that need a considerable amount of time, but Node.js can continue to process new requests while waiting, greatly improving the throughput of the system.

Stay tuned for an in-depth tutorial on Node.js asynchronous programming in a later tutorial!

Understand the Node module mechanism

Another major change in Node.js JavaScript from previous browsers is the introduction of a modular mechanism. This section is a long one, but it’s the most important step to getting started with Node.js. Go 💪!

The modularity of JavaScript

Eric Raymond defines the rules of Modularity in UNIX Programming Art:

Developers should build programs with simple parts connected by well-defined interfaces, so problems are local and parts of the program can be replaced in future releases to support new functionality. This rule is intended to save time debugging complex, verbose, and unreadable code.

The idea of “divide and conquer” is very common in the computing world, but before the ES2015 standard came along, there was no modular mechanism for JavaScript language definitions and no unified interface standard for building complex applications. People usually use a series of

<head>
  <script src="fileA.js"></script>
  <script src="fileB.js"></script>
</head>
Copy the code

There are a number of problems with this way of organizing JS code, most notably:

  • Multiple JS files imported directly into the global namespace can easily cause naming conflicts
  • The imported JS files cannot be accessed from each other. For example, filea. JS cannot be accessed from fileb. JS
  • The imported<script>Cannot be easily removed or modified

The lack of a modularity mechanism in JavaScript has been recognized as a problem, and two modularity specifications have been proposed:

  1. The Asynchronous Module Definition (AMD) specification is widely used in browsers. The most classic implementations include RequireJS.
  2. The CommonJS specification aims to provide a unified API for the JavaScript ecosystem, and Node.js implements this module standard.

prompt

The ECMAScript 2015 standard (also known as ES6) introduces a new module mechanism for the JavaScript language (called ES Modules, for ECMAScript Modules) and provides the keywords import and export. If you are interested, please refer to this article. As of now, however, Node.js support for the ES module is still experimental, so this article will not explain or advocate its use.

What is a Node module

Before we get into the mechanics of Node modules, we need to define exactly what a Node module is. Generally speaking, Node modules fall into two main categories:

  • Core modules: Built-in modules provided by Node that are compiled into binary executables when Node is installed
  • File modules: User-written modules, either self-written or installed via NPM (described below).

The file module can be a single file (ending with.js,.node, or.json), or a directory. When the module is a directory, the module name is the directory name, in two cases:

  1. There is a package.json file in the directory, which is the entry to the Node modulemainThe file to which the field points;
  2. There is a file named index in the directory with an extension.js,.node.json, this file is the module entry file.

It doesn’t matter if you can’t digest it all at once, you can read the following content first. If you forget the module definition, you can come back to it.

Analysis of Node module mechanism

Now that we know what a Node module is, let’s take a look at how Node implements the module mechanism. Specifically, Node introduces three new global objects (again Node’s own) : 1) require; Exports and 3) Module. Let’s go through them one by one.

require

Require is used to import other Node modules, and its argument takes a string representing the name or path of the module, often referred to as a module identifier. Specifically, there are three forms:

  • Write the module name directly, usually a core module or a third party file module, for exampleos,express
  • The relative path of a module to other Node modules in the project, for example./utils
  • The absolute path of the module (Not recommended!), e.g./home/xxx/MyProject/utils

prompt

When importing modules through a path, the.js suffix in the file name is usually omitted.

A code example is as follows:

// Import built-in libraries or third-party modules
const os = require('os');
const express = require('express');

// Import other modules through relative paths
const utils = require('./utils');

// Import other modules through an absolute path
const utils = require('/home/xxx/MyProject/utils');
Copy the code

You may be wondering where you find Node modules imported by name (such as Express). In fact, each module has a pathfinder list, module.paths, which will become clear when we look at module objects later.

exports

We’ve learned to use require to import content from other modules, so how do we write a Node module and export its content? The answer is exports.

For example, we write a Node module mymodule.js:

// myModule.js
function add(a, b) {
  return a + b;
}

// Export the function add
exports.add = add;
Copy the code

By adding the add function to the Exports object, external modules can use this function with the following code. Create a main.js file next to mymodule.js as follows:

// main.js
const myModule = require('./myModule');

// Call the add function in mymodule.js
myModule.add(1.2);
Copy the code

prompt

If you’re familiar with destruct assignment in ECMAScript 6, you can get the Add function in a more elegant way:

const { add } = require('./myModule');
Copy the code

module

With require and exports, we already know how to import and export Node modules, but you might still find the Node module mechanism a bit mysterious. Next, we will lift the veil of mystery and take a look at the main character behind it, the Module object.

We can add this line to the end of the myModule.js file:

console.log('module myModule:'.module);
Copy the code

At the end of main.js add:

console.log('module main:'.module);
Copy the code

It prints something like this (myModule on the left, Module on the right) :

You can see that the Module object has the following fields:

  • id: Unique identifier of the module, if the main program is being run (for example main.js)., if it is an imported module (for example mymodule.js) is equivalent to the file name (the followingfilenameField)
  • pathfilename: module path and file name, nothing to say
  • exports: What the module exports, actuallyBefore theexportsObject is pointing tomodule.exportsA reference to the. For example, for mymodule.js, we just exported itaddDelta function, and that’s why it’s hereexportsField; And main.js doesn’t export anything, soexportsField is empty
  • parentchildren: used to record import relationships between modules, for example in main.jsrequireWith myModule.js, main is myModuleparentMyModule is mainchildren
  • loaded: Whether the module is loaded, as can be seen from the above figure onlychildrenThe modules listed in the
  • paths: This is NodeSearches the list of paths to file modules, Node will search for the specified Node module from the first path to the last path. If it finds one, it will import it. If it cannot find one, an error will be reported

prompt

If you look closely, the Node file module looks like this: Look for node_modules in the current directory, then node_modules in the previous directory, and if you don’t find node_modules in the root directory, then go up to node_modules in the root directory.

Deep understanding ofmodule.exports

As we mentioned earlier, the exports object is essentially a reference to Module. exports. In other words, the following two lines are equivalent:

Export the add function
exports.add = add;

// This is the same line as above
module.exports.add = add;
Copy the code

There is actually a second way to export, assigning the add function directly to the module.exports object:

module.exports = add;
Copy the code

What’s the difference between writing it this way and exporting it the first way? The first way is to add an attribute called add on the exports object. The value of this attribute is the add function. The second way is to make the exports object directly add. It can be tricky, but be sure to understand the big difference!

In require, the distinction is clear:

// In the first way, you need to access the add attribute to get the add function
const myModule = require('myModule');
myModule.add(1.2);

// The second way to export is to use the add function directly
const add = require('myModule');
add(1.2);
Copy the code

warning

Exports = add; Exports cannot be exported because exports are essentially a reference to the module’s exports property. Assigning a direct value to exports will only change exports, not module.exports. If you find that hard to follow, let’s use the apple and Price analogy for Module and exports:

apple = { price: 1 };   // Imagine apple as module
price = apple.price;    // Exports
apple.price = 3;        // Changed apple.price
price = 3;              // Only change price, not apple.price
Copy the code

We can only set the price property with apple.price = 1, and assigning to price directly does not change apple.price.

Reconstructing the Timer script

Now that we’ve talked so much about the Node module mechanism, it’s time to return to our previous timer script timer.js. We will first create a new Node module, info.js, to print system information as follows:

const os = require('os');

function printProgramInfo() {
  console.log('Current user', os.userInfo().username);
  console.log('Current process ID', process.pid);
  console.log('Current script path', __filename);
}

module.exports = printProgramInfo;
Copy the code

Here we import the Node built-in OS module and query the system user name through os.userinfo (). Then we export the printProgramInfo function through module.exports.

Then create a second Node module, datetime.js, that returns the current time as follows:

function getCurrentTime() {
  const time = new Date(a);return time.toLocaleString();
}

exports.getCurrentTime = getCurrentTime;
Copy the code

In the module above, we chose to export the getCurrentTime function through exports.

Finally, we import the previous two modules through require in timer.js and call printProgramInfo and getCurrentTime respectively. The code is as follows:

const printProgramInfo = require('./info');
const datetime = require('./datetime');

setTimeout((a)= > {
  console.log('Hello World! ');
}, 3000);

printProgramInfo();
console.log('Current time', datetime.getCurrentTime());
Copy the code

Run timer.js again and the output should be exactly the same as before.

Having read this, I’d like to congratulate you on getting through the hardest part of getting started with Node.js! If you have a good understanding of the Node module mechanism, then I’m sure it will be much easier to learn.

Command line development: accepts input parameters

Node.js, as a platform for running JavaScript code directly from the operating system, opens up endless possibilities for front-end developers, including a series of command-line tools for implementing front-end automation workflows, such as Grunt, Gulp, and the well-known Webpack.

From this step, we will transform timer.js into a command line application. Specifically, we want timer.js to specify the time to wait (the time option) and the final output (the message option) with command line arguments:

$ node timer.js --time 5 --message "Hello Tuture"
Copy the code

throughprocess.argvRead command line arguments

Earlier in the discussion of the global object Process, I mentioned an argv property that gets an array of command-line arguments. Create an args.js file with the following code:

console.log(process.argv);
Copy the code

Then run the following command:

$ node args.js --time 5 --message "Hello Tuture"
Copy the code

Print an array:

[
  '/ Users/mRc /. NVM/versions/node/v12.10.0 / bin/node'.'/Users/mRc/Tutorials/nodejs-quickstart/args.js'.'--time'.'5'.'--message'.'Hello Tuture'
]
Copy the code

As you can see, the 0th element of the process.argv array is the actual path to node, the first element is the path to args.js, followed by all the arguments entered.

Implement command line application

From this analysis, we can get the third and fifth elements of process.argv very simply and rudely, yielding the time and message arguments, respectively. Change timer.js as follows:

const printProgramInfo = require('./info');
const datetime = require('./datetime');

const waitTime = Number(process.argv[3]);
const message = process.argv[5];

setTimeout((a)= > {
  console.log(message);
}, waitTime * 1000);

printProgramInfo();
console.log('Current time', datetime.getCurrentTime());
Copy the code

As a reminder, setTimeout is in milliseconds, and the time parameter we specified is in seconds, so we multiply it by 1000.

Run timer.js with all the parameters I just mentioned:

$ node timer.js --time 5 --message "Hello Tuture"
Copy the code

Wait 5 seconds and you’ll see the prompt text for Hello Tuture!

Obviously, there are major issues with the current version: the format of input parameters is fixed and inflexible, such as switching the order of time and message, and there is no way to check whether the user has entered the specified parameters and the format is correct. If you want to implement the above features yourself, it will be a lot of effort, and probably a lot of bugs. Is there a better plan?

NPM: Primordial powers are given to you

Starting with this section, you will no longer be writing code alone. You have millions of JavaScript developers behind you, all with NPM. NPM include:

  • NPM command-line tool (also installed with Node installation)
  • The NPM Centralized dependency Registry holds NPM packages shared by other JavaScript developers
  • NPM website, you can search for NPM packages, manage NPM accounts, etc

NPM movement of

Let’s first open the terminal (command line) and check if the NPM command is available:

6.10.3 $NPM - vCopy the code

Then run the following command in the current directory (that is, the folder where the timer.js was edited) to initialize the current project as an NPM project:

$ npm init
Copy the code

NPM will ask you a series of questions, which you can either press enter or answer carefully, to create a package.json file. The package.json file is the core of an NPM project and records all the key information about the project as follows:

{
  "name": "timer"."version": "1.0.0"."description": "A cool timer"."main": "timer.js"."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git"."url": "git+https://github.com/mRcfps/nodejs-quickstart.git"
  },
  "author": "mRcfps"."license": "ISC"."bugs": {
    "url": "https://github.com/mRcfps/nodejs-quickstart/issues"
  },
  "homepage": "https://github.com/mRcfps/nodejs-quickstart#readme"
}

Copy the code

Most of these fields have clear meanings, such as Name project name, Version version number, Description description, Author author, and so on. But this is the scripts field that might confuse you, and we’ll cover it in more detail in the next section.

Install the NPM package

Next we’ll look at the most common NPM command, install. Yes, it is no exaggeration to say that NPM install is the most commonly used NPM command by a JavaScript programmer.

Before installing the NPM packages we need, we need to explore what packages are available to us. In general, we can do a keyword search on the NPM website (remember to use English), such as command line:

The first result that comes out is commander, which is exactly what we need. Click on it to get the installation instructions and use documentation. We also want an animation that is “loading” to enhance the user’s experience.

The second result, ORA, also meets our needs. Now let’s install these two NPM packages:

$ npm install commander ora
Copy the code

Json has a very important dependencies field:

"Dependencies" : {" commander ", "^ 4.0.1", "ora" : "^ 4.0.3"}Copy the code

This field records the direct dependencies of our project. As opposed to direct dependencies are indirect dependencies, such as commander and ORA dependencies, which we don’t usually care about. All NPM packages (direct and indirect dependencies) are stored in the node_modules directory of the project.

prompt

Node_modules are usually too many files to be added to Git version control, and NPM projects you download from the web will only have package.json, so simply run NPM install to download and install all dependencies.

The entire package.json code looks like this:

{
  "name": "timer"."version": "1.0.0"."description": "A cool timer"."main": "timer.js"."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git"."url": "git+https://github.com/mRcfps/nodejs-quickstart.git"
  },
  "author": "mRcfps"."license": "ISC"."bugs": {
    "url": "https://github.com/mRcfps/nodejs-quickstart/issues"
  },
  "homepage": "https://github.com/mRcfps/nodejs-quickstart#readme"."dependencies": {
    "commander": "^ 4.0.1." "."ora": "^ 4.0.3"}}Copy the code

About version Number

In software development, version number is a very important concept, there are large or small differences between different versions of software. NPM adopts Semantic Versioning (semver), which is specified as follows:

  • Version format: Major version number. Second version. Revision number
  • A major version number change means incompatible API changes
  • The change in the secondary version number means a backward compatible functional addition
  • The revision number change means a backward-compatible problem fix

prompt

Backward compatibility is simply a matter of adding functionality.

So in the Dependencies field of package.json, you can specify the version as follows:

  • Accurate version: e.g.1.0.0, must only install version as1.0.0The dependence of
  • Lock major and minor versions: can be written as1.0,X 1.0.~ 1.0.0, then you might install for example1.0.8The dependence of
  • Only the major version is locked: can be written as1,1.x^ 1.0.0(npm installDefault form), then you might install for example1.1.0The dependence of
  • The latest version: can be written as*x, then directly install the latest version (not recommended)

You may have noticed that NPM also creates a package-lock.json file that locks the exact version numbers of all direct and indirect dependencies, or provides the exact description of the node_modules directory, This ensures that everyone developing on the project has exactly the same NPM dependencies.

Standing on the shoulders of giants

After a brief read of the COMMANDER and ORA documentation, we are ready to start using the timer.

const program = require('commander');
const ora = require('ora');
const printProgramInfo = require('./info');
const datetime = require('./datetime');

program
  .option('-t, --time <number>'.'Wait time (seconds)'.3)
  .option('-m, --message <string>'.'Information to Output'.'Hello World')
  .parse(process.argv);

setTimeout((a)= > {
  spinner.stop();
  console.log(program.message);
}, program.time * 1000);

printProgramInfo();
console.log('Current time', datetime.getCurrentTime());
const spinner = ora('Loading, please wait... ').start();
Copy the code

This time, we run timer.js again:

$ node timer.js --message "Primordial power! --time 5
Copy the code

It’s spinning!

Try out NPM scripts

In the final section of this tutorial, we will take a brief look at NPM scripts, also known as NPM scripts. As mentioned earlier in package.json, there is a field called scripts that defines all NPM scripts. We found that the package.json file created with NPM init has a test script added by default:

"test": "echo \"Error: no test specified\" && exit 1"
Copy the code

That string of commands is what the test script will do, which we can execute with the NPM test command:

$ npm test

> [email protected] test /Users/mRc/Tutorials/nodejs-quickstart
> echo "Error: no test specified" && exit 1

Error: no test specified
npm ERR! Test failed.  See above for more details.
Copy the code

After our initial experience with NPM Scripts, it’s important to understand that NPM Scripts fall into two broad categories:

  • Predefined scripts: e.g.test,start,install,publishWait, go straight throughnpm <scriptName>Run, for examplenpm test, all predefined scripts can be viewedThe document
  • Custom scripts: Scripts other than those provided with the preceding scripts must be passednpm run <scriptName>Run, for examplenpm run custom

Now let’s start adding two NPM scripts to the Timer project, start and Lint. The first one is predefined and is used to launch our timer.js; The second is static code review, which checks our code at development time. Install the ESLint NPM package first:

$ npm install eslint --save-dev
$ # or
$ npm install eslint -D
Copy the code

Note that we added a -d or –save-dev option to indicate that ESLint is a development dependency and is not needed for actual project release or deployment. NPM adds all development dependencies to the devDependencies field. Then add the start and lint scripts as follows:

{
  "name": "timer"."version": "1.0.0"."description": "A cool timer"."main": "timer.js"."scripts": {
    "lint": "eslint **/*.js"."start": "Node timer.js -m 'ready' -t 3"."test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git"."url": "git+https://github.com/mRcfps/nodejs-quickstart.git"
  },
  "author": "mRcfps"."license": "ISC"."bugs": {
    "url": "https://github.com/mRcfps/nodejs-quickstart/issues"
  },
  "homepage": "https://github.com/mRcfps/nodejs-quickstart#readme"."dependencies": {
    "commander": "^ 4.0.1." "."ora": "^ 4.0.3"
  },
  "devDependencies": {
    "eslint": "^ 6.7.2." "}}Copy the code

To use ESLint, you need a configuration file, create the.eslintrc.js file (note the dot at the front) with the following code:

module.exports = {
    "env": {
        "es6": true."node": true,},"extends": "eslint:recommended"};Copy the code

Run NPM start to see that our timer.js script was successfully run; NPM run Lint, on the other hand, produces no result (static check passed).

NPM Scripts may seem mundane, but it provides a very convenient workflow for project development. For example, building a project used to require very complex commands, but if you implement a Build NPM script, when your colleagues get their hands on the code, they can simply execute the NPM run build and start building without worrying about the technical details behind it. In future node.js or front-end studies, we will use various NPM scripts to define our workflow in real projects, and people will gradually understand its power.

See you next time: Listen for the exit event

In the final section of this tutorial, we’ll give you a brief taste of Node’s event mechanism. Node’s event mechanism is complex enough to cover half a book, but this tutorial is intended to give you a glimpse of Node events with a very simple example.

prompt

If you’ve ever written event handling (such as mouse clicks) in web (or other user interface) development, the way Events are handled in Node will be familiar and intuitive.

We briefly mentioned the callback function earlier. In fact, the callback function and event mechanism together make up the asynchronous world of Node. Specifically, events in Node are implemented through the EventEmitter class in the Events core module. EventEmitter includes two of the most critical approaches:

  • on: used to listen for events
  • emit: is used to trigger new events

Take a look at the following code snippet:

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

// Listen for connect events and register callback functions
emitter.on('connect'.function (username) {
  console.log(username + 'Connected');
});

// Trigger the connect event with an argument (username above)
emitter.emit('connect'.'A tooker');
Copy the code

Running the code above should output the following:

A map finch has been connectedCopy the code

Many objects in Node inherit from EventEmitter, including the familiar Process global object. In the previous timer.js script, we listened for the exit event (the end of the Node process) and added a custom callback function to print the message “see you next time” :

const program = require('commander');
const ora = require('ora');
const printProgramInfo = require('./info');
const datetime = require('./datetime');

program
  .option('-t, --time <number>'.'Wait time (seconds)'.3)
  .option('-m, --message <string>'.'Information to Output'.'Hello World')
  .parse(process.argv);

setTimeout((a)= > {
  spinner.stop();
  console.log(program.message);
}, program.time * 1000);

process.on('exit', () = > {console.log('See you next time.');
});

printProgramInfo();
console.log('Current time', datetime.getCurrentTime());
const spinner = ora('Loading, please wait... ').start();
Copy the code

After the program exits, a string of “See you next time ~” is printed. Why can’t you add a program exit logic to the setTimeout callback, you might ask? Because it is very likely that our program will exit for reasons other than normal execution (i.e. waiting for the specified time) (such as throwing an exception or forcing exit with process.exit), we can make sure that the exit event callback is executed in all cases by listening for exit events. If you still don’t get it, take a look at this diagram:

prompt

The process object also supports other commonly used events, such as SIGINT (triggered when the user presses Ctrl+C), and so on, as you can see in this document.

This quick start to Node.js concludes and hopefully serves as a foundation for further exploration of Node.js and front-end development. The exit event has been triggered, so I’ll see you next time

Want to learn more exciting practical skills tutorial? Come and visit the Tooquine community.