Note | NodeJs入门

NodeJS是什么?

Node.js是一个基于Crome V8引擎的JavaScript运行时,主要用于web服务器。(Node.js is built on top of the Google Chrome V8 JavaScript engine, and it's mainly used to create web servers)——NodeJs官方文档

广义理解

  • 一个JavaScript运行时。
    • Chrome V8Js在浏览器中的运行时,NodeJsJs在服务器中的运行时
    • NodeJS不是一名语言是运行时
  • 内置开发包管理工具:npm(也可以使用yarnpnmp等其他的包管理工具)
  • 提供内置的开发包
  • 代码执行为异步非阻塞式(传统的代码执行为阻塞式
  • 代码组织规范:
    • module:exports,require(export,import)
      • 因为是NodeJS的一个运行时,其定义了代码与代码间的一种组织,而这里的代码就是靠module组织起来的
      • modulemodule之间可以使用exports来对外暴露其自身的函数
      • 使用require来使用其他module暴露给自己的函数
    • package:package.json,(dependecy)
      • 所有的module在一个目录里面时通过package.json文件来进行管理的
  • NodeJS提供了npmjs.com来共享第三方包的生态

进入NodeJS的交互模式

在控制台输入 node 进入交互模式,此时可以输入对应的 js 代码运行。

image-20230305153740239

实际上与浏览器中的控制台差不多,但是在一些情况下有区别 image-20230305153844364

这也说明了Js是一种脚本语言,无需实现编译成机器码,但是需要运行时(运行环境)

浏览器内置运行时与NodeJS运行时的区别

  • 变量赋值

    1
    
    var a = 1;
    
    • 在浏览器中

      1
      
      window.a
      
    • NodeJS

      1
      
      global.a
      

开发模式

新建文件index.js

1
2
3
4
5
console.log("hello world");
// 输出当前运行平台
console.log(process.platform);
// 输出当前的环境变量
console.log(process.env);

在其建立的目录下使用命令:node index.js或者node .

建立自己的module并使用

新建文件modulex.js

1
2
3
4
5
6
7
/**
 * modulex.js
 */
var a = 1;
// 向外暴露变量 a 与 b
module.exports.a = a;
module.exports.b = 2;

引入刚才建立的modulex使用require,对刚才新建的index.js进行修改

1
2
3
// 使用模块
var m = require('./modulex');
console.log(m);
1
2
> node index.js
{ a: 1, b: 2 }

也可以向外暴露函数

1
2
3
4
5
6
7
8
/**
 * modulex.js
 */
var a = 1;
// 向外暴露函数
module.exports = function(x) {
    console.log(`输入的参数为${x}`);
}

使用

1
2
3
4
// 使用模块
var fn = require('./modulex');
console.log(fn);
fn(111);
1
2
3
> node index.js
[Function (anonymous)]
输入的参数为111

备注:

  • 因为本身只有一种暴露方式所以modulex.js文件中的module是可以不用写的(执行效果是一眼的)
1
2
3
4
5
6
7
/**
 * modulex.js
 */
var a = 1;
// 向外暴露变量 a 与 b
exports.a = a;
exports.b = 2;

使用NodeJS内置包模块(fs)

以读取文件为案例:

  • 同步阻塞
1
2
3
4
5
6
7
8
/**
 * index.js
 */
const { readFileSync } = require('fs');
console.log('reading ...');
const txt = readFileSync('./modulex.js', 'utf-8');
console.log(txt);
console.log('Done!')
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
> node index.js
reading ...
/**
 * modulex.js
 */
var a = 1;
// 向外暴露函数
module.exports = function(x) {
    console.log(`输入的参数为${x}`);
}
Done!
  • 异步非阻塞
1
2
3
4
5
6
7
8
9
/**
 * index.js
 */
const { readFile } = require('fs');
console.log('reading ...');
readFile('./modulex.js', 'utf-8', (err, txt) => {
    console.log(txt);
});
console.log('Done???')
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
> node index.js
reading ...
Done???
/**
 * modulex.js
 */
var a = 1;
// 向外暴露函数
module.exports = function(x) {
    console.log(`输入的参数为${x}`);
}

可以看到异步非阻塞的情况下是先输出Done字眼的,这说明执行文件读取这步并没有阻塞代码的执行。

  • Promise

    • 可以通过asyncawait来达到阻塞代码的效果
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    /**
     * index.js
     */
    const { readFile } = require('fs').promises;
    async function rdFile() {
        console.log('reading ...');
        const txt = await readFile('./modulex.js', 'utf-8');
        console.log(txt);
        console.log('done');
    }
    
    rdFile();
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    > node index.js
    reading ...
    /**
     * modulex.js
     */
    var a = 1;
    // 向外暴露函数
    module.exports = function(x) {
        console.log(`输入的参数为${x}`);
    }
    done
    
    • promise
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    /**
     * index.js
     */
    const { readFile } = require('fs').promises;
    async function rdFile() {
        console.log('reading ...');
        const prom = readFile('./modulex.js', 'utf-8');
        prom.then(rslt => {
            console.log(rslt);
        })
        console.log(prom);
        console.log('done');
    }
    
    rdFile();
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    > node index.js
    reading ...
    Promise { <pending> }
    done
    /**
     * modulex.js
     */
    var a = 1;
    // 向外暴露函数
    module.exports = function(x) {
        console.log(`输入的参数为${x}`);
    }
    
    1. 上面这种情况 rdFile 返回的是 promise

    2. 返回 promise 之后程序不会阻塞,而是背地里回去后台读取文件

    3. 程序就会先后执行 console.log(prom);console.log('done');这两句

    4. 文件读取完成才执行then方法中的回调函数,输出文件的内容

使用npm平台与第三方包模块

使用npm init让当前目录具有包管理能力,这样会在目录下新建一个package.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "name": "node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
  • 安装单独的依赖包时,npm install <packageName>

安装express

1
> npm i express

补充(一些参数的说明):

  • npm installnpm i 等价,都是安装package.json文件中的依赖包。

  • --save 等同于-S (常用,可保存在package.json文件中

    -S, --save 安装包信息将加入到 dependencies(生产阶段的依赖,也就是项目运行时的依赖,就是程序上线后仍然需要依赖)

  • --save-dev 等同于 -D

    -D, --save-dev 安装包信息将加入到 devDependencies(开发阶段的依赖,就是我们在开发过程中需要的依赖,只在开发阶段起作用。)

  • –-only=dev:添加--only=dev安装项目所需依赖时,只有 devDependencies 字段中的依赖包会被安装,dependencies 字段中的依赖包不会被安装。

  • --production:添加--production安装项目所需的依赖时,只有 dependencies 字段中的依赖包会被安装,devDependencies 中的依赖包不会被安装。

修改index.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/**
 * index.js
 */
const express = require('express');
const app = express();

app.get('/', function(req, res){
    res.send('Hello World');
});

app.listen(8089);

效果:

image-20230305165517357

参考文献