wallleap / myblogs

blog, Issue
https://myblog.wallleap.cn
4 stars 1 forks source link

NodeJs学习笔记 #51

Open wallleap opened 4 years ago

wallleap commented 4 years ago

title: 作为前端需要了解的 Node 知识 date: 2020-06-14 11:33 updated: 2020-06-14 11:33 cover: //cdn.wallleap.cn/img/pic/cover/202302oHImDg.jpg category: 技术杂谈 tags:

Node 知识

一、基本知识

1、命令行窗口

又称 cmd 窗口、终端、shell

打开方式:

前面显示的为目前所在的目录

常用的命令

环境变量(Windows 系统中的变量)

2、进程和线程

进程

线程

二、Node.js 简介

nodejs 是一个能够在服务器端运行 js 的开放源代码、跨平台的 js 运行环境

node 采用 google 开发的 v8 引擎运行 js 代码,使用 event-driven、non-blocking I/O 模型,使其轻量又高效

三、node 使用

1、安装

官网下载安装包,安装即可

推荐使用 nvm 管理 node 版本

  1. 下载 nvm 安装包,安装,或者使用包管理器例如 brew 安装:brew install nvm(Win 找到官网后下载安装)
  2. 安装完成后,打开命令行窗口,输入 nvm -v,如果出现版本号,则安装成功
  3. 接着输入 nvm install node,安装最新版本的 node
  4. 多版本管理
    • 使用 nvm install 版本号 安装指定版本的 node
    • 可以使用 nvm ls 查看已安装的 node 版本
    • 使用 nvm use 版本号 切换 node 版本

安装完成后,打开命令行窗口,输入 node -v,如果出现版本号,则安装成功

安装完成后,会自动安装 npm 包管理器

运行 node,进入 node 命令行窗口,可以直接运行 js 代码

node
> var i = 0
> console.log(i)

还可以直接运行 js 文件

node hello.js

四、COMMONJS 规范

1、ECMAScript 标准的缺陷

2、模块化 module.js

在 node 中,一个 js 就是一个模块

在 Node 中,每一个 js 文件中的 js 代码都是独立运行在一个函数中,而不是全局作用域,所以一个模块中的变量和函数在其他模块中无法访问

我们可以通过 exports 来向外部暴露变量和方法,只需要将要暴露给外部的变量或方法设置为 exports 的属性即可

exports.x = "我是 module.js中的x"
exports.fn = function(){}

在 Node 中有一个全局对象 global,它的作用和网页中 window 类似,在全局中创建的变量都会作为 global 的属性保存,在全局中创建的函数都会作为 global 的方法保存

var a = 10;
console.log(global.a);

arguments

在 node 执行模块中的代码时,它首先会在代码的最顶部添加代码 function(exports, require, module, __filename, __dirname){,在代码的最底部,添加代码 }

实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递进了 5 个实参(arguments.length 查看参数长度)

在 node 中通过 require() 函数来引入外部的模块,require() 可以传递一个文件的路径作为参数,node 将会自动根据该路径来引入外部模块,这里的路径如果使用相对路径,必须以 ... 开头

使用 require 引入模块后,该函数会返回一个对象,这个对象代表的是引入的模块

var md = require("./module.js");
console.log(md)

模块分为两大类

3、CommonJS 规范

CommonJS 规范的提出,主要是为了弥补当时 JavaScript 没有标准的缺陷

CommonJS 规范为 JS 制定了一个美好的愿景,希望 JS 能够在任何地方运行

CommonJS 规范对模块的定义十分简单

五、包 Package

1、简介

2、包结构

包实际上就是一个压缩文件,解压以后还原为目录

符合规范的目录,应该包含如下文件:

3、包描述文件

包描述文件用于表达非代码相关的信息,它是一个 JSON 格式的文件—— package.json,位于包的根目录下,是包的重要组成部分

package.json 中的字段(JSON 中不能写注释)

  1. 标识
  2. 依赖
  3. 运行/打包

通过 npm run 可以查看当前可执行的脚本命令(script 字段),npm run 脚本名称 可以执行对应的脚本命令

六、NPM(Node Package Manager)

1、简介

CommonJS 包规范是理论,NPM 是其中一种实践

对于 Node 而言,NPM 帮助其完成了第三方模块的发布、安装和依赖等。借助 NPM,Node 与第三方模块之间形成了很好的一个生态系统

包管理工具,用于 Node 模块的管理,除了 npm 之外,还有 yarn、cnpm、pnpm 等

现在推荐使用 pnpm 代替 npm,pnpm 是一个快速、零配置的 Node 包管理工具,它使用硬链接和符号链接来降低磁盘空间的使用,它的速度也非常快,它的速度是 npm 的 3~5 倍,yarn 的 2~3 倍

2、NPM 命令

淘宝镜像:https://npm.taobao.org

一般不直接设置官方原版 npm 替换为其他源,可以使用 cnpm

npm install -g cnpm --registry=https://registry.npmmirror.com

注:

七、Buffer(缓冲区)

Buffer 的就结构和数组很像,操作的方法也和数组类似

数组中不能存储二进制的文件,而 buffer 就是专门用来存储二进制数据的

使用 buffer 不需要引入模块,直接使用即可

var str = "hello"
// 将一个字符串保存到buffer中
var buf = Buffer.from(str)
console.log(buf)
console.log(buf.length,str.length)  // 占用内存的大小,字符串的长度

在 buffer 中存储的都是二进制数据,但是在显示的时候都是以 16 进制的形式显示的,buffer 中每一个元素的范围是从 00 到 ff (0~255) 00000000~11111111 8 位(bit) = 1字节(byte),buffer 中的一个元素占用内存的一个字节

ps:一个汉字 3 字节,一个英文字母 1 字节

buffer 的大小一旦确定,则不能修改,Buffer 实际上是对底层内存的直接操作

// 创建一个指定大小的buffer
var buf = new Buffer(10) // 10个字节的buffer
// buffer构造函数都是不推荐使用的
var buf2 = Buffer.alloc(10)   // 全都是00
buf2[0] = 88
buf2[1] = 255
buf2[2] = 0xaa
buf2[3] = 556
// 1000101100截取后八位
buf2[10] = 15  // 没改变
// 只要数字在控制台或页面中输出一定是10进制
console.log(buf2[2])
console.log(buf2[2].toString(16))  // 可以这样转为16进制显示

var buf3 = Buffer.allocUnsafe(10)  // 创建一个指定大小的buffer,但是buffer中可能含有敏感数据,不全为00

https://nodejs.cn

八、文件系统(File System)

1、简介

文件系统简单来说就是通过 Nodejs 来操作系统中的文件

在 Node 中,与文件系统的交互是非常重要的,服务器的本质就是将本地的文件发送给远程的客户端

Node 通过 fs 模块来和文件系统进行交互

fs 模块提供了一些标准文件访问 API 来打开、读取、写入文件,以及与其交互

要使用文件系统,需要先引入 fs 模块,fs 是核心模块,直接引入不需要下载;要使用 fs 模块,首先需要对其进行加载

const fs = require('fs')

2、同步和异步调用

3、同步、异步文件写入

同步文件的写入

操作步骤:

  1. 打开文件

    • fs.openSync(path, flags[, mode])

    • path 要打开文件的路径

    • flags 打开文件要做的操作的类型:r 只读的、w 可写的

    • mode 设置文件的操作权限,一般不传

    • 返回值: 返回一个文件的描述符,可以通过该描述符来对文件进行各种操作

      var fs = require("fs");
      var fd = fs.openSync("hello.txt", "w");
      // console.log(fd)
  2. 向文件中写入内容

    • fs.writeSync(fd, string[, position[, encoding]])

    • fd 文件的描述符,需要传递要写入的文件的描述符

    • string 要写入的内容

    • position 写入的起始位置

    • encoding 写入的编码,默认 utf-8

      fs.writeSync(fd, "这是写入的内容")
  3. 保存并关闭文件

    • fs.closeSync(fd)
    • fd 要关闭的文件的描述符

异步文件写入:

  1. 打开 fs.open(path, flags[, mode], callback)

    • 用来打开一个文件

    • 异步方法没有返回值,有返回值的都是同步方法。异步调用的方法,结果都是通过回调函数参数返回的。

    • callback 回调函数两个参数(arguments):

      • err 错误对象,如果没有错误则为 null

      • fd 文件的描述符

      var fs = require("fs")
      var f
      fs.open("hello.txt","w",function(err, fd){
        // console.log('回调函数中的代码')  // callback中的代码会在读取完毕之后执行
        if(!err){
          f = fd
        }else{
          console.log(err)
        }
      })
      console.log("open下的代码") // 能比上面的更早执行
  2. 写入 fs.write(fd, string[, position[, encoding]], callback)

    • 用来异步写入一个文件
  3. 关闭 fs.close(fd, callback)

    • 用来关闭文件

      var fs = require("fs")
      fs.open("hello.txt","w",function(err, fd){
      if(!err){
      fs.write(fd, "这是异步写入的内容",function(err)    {
      if(!err){
        console.log('写入成功')
      }
      fs.close(fd, function(err){
        if(!err){
          console.log('文件已关闭')
        }
      })
      })
      }else{
      console.log(err)
      }
      })

4、简单文件写入

fs.writeFile(file, data[, options], callback)

模式

fs.writeFileSync(file, data[, options])

同步简单写入

5、流式文件写入

同步、异步、简单文件的写入都不适合大文件的写入,性能较差,容易导致内存溢出

流式文件写入:

fs.createWriteStream(path[, options])

var fs = require("fs")
var ws = fs.createWriteStream("hello.txt")
// 可以通过监听流的open和close事件来监听流的打开和关闭
// ws.on("open", function{  // on绑定一个长期有效的事件
ws.once("open", function{   // once绑定一次性的事件,在触发一次之后事件自动失效
  console.log("流打开了")
})
ws.once("close", function{
  console.log("流关闭了")
})
// 通过ws向文件中输出内容
ws.write("通过可写流写入文件的内容1")
ws.write("通过可写流写入文件的内容2")
ws.write("通过可写流写入文件的内容3")
// 只要流还存在就可以接着写入
// 关闭流
// ws.close()    // 这个在传入的方向断开流,文件没到管子里
ws.end()  // 在传出的这一方断开流,数据已经在管子里了

6、文件的读取

同步文件读取、异步文件读取、简单文件读取

fs.readFile(path[, options], callback)

fs.readFileSync(path[, options])

var fs = require("fs")
var path="C:/Users/Shinlon/a.mp3"
fs.readFile("hello.txt", function(err, data) {
  if(!err) {
    console.log(data)  // buffer通用性更高
    // console.log(data.toString())文本可以,其他不行
    fswriteFile("hello.mp3", data, function(err) {
      if(!err) {
        console.log("文件写入成功")
      }
    })
  }
})

流式文件读取

var fs = require("fs")
// 创建一个可读流
var rs = fs.createReadStream("an.jpg")
// 监听流的开启和关闭
rs.once("open", function() {
  console.log("可读流打开了")
})
rs.once("close", function() {
  console.log("可读流关闭了")
})
// 读取一个可读流中的数据,必须要为可读流绑定一个 data 事件,data 事件绑定完毕,它会自动开始读取数据
rs.on("data", function(data) {
  console.log(data) // 参数就是数据  data.length 最大 65536 字节
})

可读流、可写流复制一个大文件

var fs = require("fs")
var rs = fs.createReadStream("an.jpg")
var ws = fs.createWriteStream("an.jpg")
rs.once("open", function() {
  console.log("可读流打开了")
})
rs.once("close", function() {
  console.log("可读流关闭了")
  // 数据读取完毕,关闭可写流
  ws.end()
})
ws.once("open", function() {
  console.log("可写流打开了")
})
ws.once("close", function() {
  console.log("可写流关闭了")
})
rs.on("data", function(data) {
  ws.write(data)
})

简单的方式

var fs = require("fs")
var rs = fs.createReadStream("an.jpg")
var ws = fs.createWriteStream("an.jpg")
rs.once("open", function() {
  console.log("可读流打开了")
})
rs.once("close", function() {
  console.log("可读流关闭了")
})
ws.once("open", function() {
  console.log("可写流打开了")
})
ws.once("close", function() {
  console.log("可写流关闭了")
})
// pipe()可以将可读流中的内容直接输出到可写流中
rs.pipe(ws)

7、fs 的其他方法

验证路径是否存在

var fs = require("fs")
var isExists = fs.exitsSync("a.mp3")
// console.log(isExists)

获取文件信息

fs.stat("a.mp3", function(err, stat) {
  console.log(stat)
})

stat 参数的一些属性、方法

删除文件

fs.unlinkSync("hello.txt")

列出文件

fs.readdir(".", function(err, files) {
  if(!err){
    console.log(files)
  }
})

截断文件

fs.truncateSync("hello.txt", 3)

建立目录

fs.mkdirSync("hello")

删除目录

fs.rmdirSync("hello")

重命名文件和目录

fs.rename("a.mp3", "new.mp3", function(err) {
  if(!err){
    console.log("success")
  }
})

监视文件更改写入

fs.watchFile("hello.txt", function {
  console.log(prev.size)
  console.log(curr.size)
})

时间间隔,配置选项中

fs.watchFile("hello.txt", { interval: 1000 }, function {
  console.log(prev.size)
  console.log(curr.size)
})