node程序传递参数
以如下方式启动 Node.js 进程:
$ node index.js one two=three four
获取参数其实是在process的内置对象中的
如果我们直接打印这个内置对象,它里面包含特别的信息:其他的一些信息,比如版本、操作系统等
将生成输出:
- e现在,我们先找到process的内置对象中argv属性
console.log(process.argv)
//输出
[
'D:\\software\\node\\node.exe',
'D:\\newProject\\node\\node_Code\\top.js',
'one',
'two=three',
'four'
]
全局对象
特殊的全局对象
常见的全局对象
-
process对象:process提供了Node进程中相关的信息:
-
比如Node的运行环境、参数信息等
-
将一些环境变量(.env文件)读取到 process 的 env 对象中
//这里要使用一个叫dotenv的库,可以把项目中的.env文件读取到我们的process.env中去 const dotenv = require('dotenv'); dotenv.config(); module.exports = { APP_HOST, APP_PORT, MYSQL_HOST, MYSQL_PORT, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD, } = process.env;
-
-
console对象:提供了简单的调试控制
- 更加详细的查看官网文档:https://nodejs.org/api/console.htm
-
定时器函数:在Node中使用定时器有好几种方式
- setTimeout(callback, delay[, …args]):callback在delay毫秒后执行一次
- setInterval(callback, delay[, …args]):callback每delay毫秒重复执行一次
- setImmediate(callback[, …args]):callbackI / O事件后的回调的“立即”执行
- process.nextTick(callback[, …args]):添加到下一次tick队列中
global对象
事实上前端我们提到的process、console、setTimeout等都有被放到global中
global和window的区别
-
在浏览器中,全局变量都是在window上的,比如有document、setInterval、setTimeout、alert、console等等
-
在Node中,我们也有一个global属性,并且看起来它里面有很多其他对象
-
但是在浏览器中执行的JavaScript代码,如果我们在顶级范围内通过var定义的一个属性,默认会被添加到window 对象上
var name = 'gzy'; console.log(window.name) //'gzy'
-
但是在node中,我们通过var定义一个变量,它只是在当前模块中有一个变量,不会放到全局中
var name = 'gzy' console.log(golbal.name) //undefined
内置模块
path模块
path的resolve()方法
官方:从右到左处理给定的路径序列,每个后续路径都被预置,直到构造出绝对路径为止;
如果在处理完所有给定的路径段后,尚未生成绝对路径,则使用当前工作目录。
除非路径解析为根目录,否则将对结果路径进行规 范化并删除尾部斜杠。忽略零长度路径段。
如果没有传递任何路径段,path.resolve()将返回当前工作目录的绝对路径。
// __dirname 路径是 D:\newProject\node\node_Code
const path = require("path")
//resolve函数会判断我们拼接的路径前面是否有/或../或./
//1.如果有表示是一个绝对路径,会返回对应的拼接路径
console.log(path.resolve(__dirname,"index.js"));//D:\newProject\node\node_Code\index.js
console.log(path.resolve(__dirname,"./index.js"));//D:\newProject\node\node_Code\index.js
console.log(path.resolve(__dirname,"../index.js"));//D:\newProject\node\index.js
console.log(path.resolve(__dirname,"../../index.js"));//D:\newProject\index.js
//2.如果没有,那么会和当前执行文件所在的文件夹进行路径的拼接
console.log(path.resolve("/User/why","http/app","/text.txt")); //D:\text.txt
console.log(path.resolve("/User/why","/http/app","text.txt"));//D:\http\app\text.txt
console.log(path.resolve("/User/why","http/app","text.txt"));//D:\User\why\http\app\text.txt
console.log(path.resolve(__dirname,"/index.js")); //D:\index.js
//2.1 如果前面有/开头的路径,那么后面的../就会相对这个路径进行匹配
console.log(path.resolve("/http/app","./text.txt")); //D:\http\app\text.txt
console.log(path.resolve("/http/app","../text.txt")); //D:\http\text.txt
console.log(path.resolve("/http/app","../../text.txt")); //D:\text.txt
//webpack常见的封装方法
const resolve = dir => path.resolve(__dirname,dir)
console.log(resolve("app.js")); //D:\newProject\node\node_Code\app.js
path获取路径信息的方法
const path = require("path")
//1.获取路径的信息
const filepath = '/User/why/abc.txt'
console.log(path.dirname(filepath)); //获取文件的绝对路径 User/why/
console.log(path.basename(filepath)); //获取文件名字 abc.txt
console.log(path.extname(filepath)); //获取文件的后缀名 .txt
path.join()
- resolve会判断拼接的路径字符串中,从右到左查找,是否有/ 或 …/开头的路径(例如/user/why)
- 如果有表示是一个绝对路径,会返回对应的拼接路径
- 如果没有,那么会和当前执行文件所在的文件夹进行路径的拼接
- join方法更像存粹的路径进行拼接
console.log(path.join(__dirname,"index.js"));//D:\newProject\node\node_Code\index.js
console.log(path.join(__dirname,"./index.js"));//D:\newProject\node\node_Code\index.js
console.log(path.join(__dirname,"../index.js"));//D:\newProject\node\index.js
console.log(path.join(__dirname,"../../index.js"));//D:\newProject\index.js
console.log(path.join("/User/why","http/app","/text.txt")); //\User\why\http\app\text.txt
console.log(path.join("/User/why","/http/app","text.txt"));//\User\why\http\app\text.txt
console.log(path.join("/User/why","http/app","text.txt"));//\User\why\http\app\text.txt
console.log(path.join(__dirname,"/index.js")); //D:\newProject\node\node_Code\index.js
console.log(path.join("/http/app","./text.txt")); //D:\http\app\text.txt
console.log(path.join("/http/app","../text.txt")); //D:\http\text.txt
console.log(path.join("/http/app","../../text.txt")); //D:\text.txt
console.log(path.join("index.js")); //index.js
console.log(path.join("/index.js")); //\index.js
console.log(path.join()); // .代表当前的工作目录
fs模块
fs的API介绍
API大多数都提供三种操作方式:
- 方式一:同步操作文件:代码会被阻塞,不会继续执行;
- 方式二:异步回调函数操作文件:代码不会被阻塞,需要传入回调函数,当获取到结果时,回调函数被执行
- 方式三:异步Promise操作文件:代码不会被阻塞,通过 fs.promises 调用方法操作,会返回一个Promise, 可以通过then、catch进行处理;
flag标识
我们先来看flag:
flag的值有很多:https://nodejs.org/dist/latest-v14.x/docs/api/fs.html#fs_file_system_flags
- w 打开文件写入,默认值;
- w+打开文件进行读写,如果不存在则创建文件;
- r+ 打开文件进行读写,如果不存在那么抛出异常;
- r打开文件读取,读取时的默认值;
- a打开要写入的文件,将流放在文件末尾(追加)。如果不存在则创建文件;
- a+打开文件以进行读写,将流放在文件末尾(朱家)。如果不存在则创建文;
a和 w的区别? a是在文件末尾继续添加数据,而w则是在把数据覆盖在文件上边
encoding选项
我们再来看看编码:
- coderwhy大佬简书上写过一篇关于字符编码的文章:https://www.jianshu.com/p/899e749be47c
- 目前基本用的都是UTF-8编码;
获取文件的状态
const fs = require('fs')
//同步的方式
const fileInfo = fs.statSync("./abc.txt")
console.log(fileInfo);
//异步的callback方式
fs.stat("./abc.txt",(err,fileInfo) => {
if(err) return;
console.log(fileInfo);
})
//异步的Promise方式
fs.promises.stat("./abc.txt").then(fileInfo => {
console.log(fileInfo);
}).catch(err => console.log(err))
//输出
Stats {
dev: 2665899921,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 8162774325260815,
size: 7,
blocks: 0,
atimeMs: 1659069196538.233,
mtimeMs: 1657853572225.3513,
ctimeMs: 1657853572225.3513,
birthtimeMs: 1657852910305.4011,
atime: 2022-07-29T04:33:16.538Z,
mtime: 2022-07-15T02:52:52.225Z,
ctime: 2022-07-15T02:52:52.225Z,
}
文件的读取
const fs = require('fs')
//读取的文件获取的是一个buffer
//同步的方式
let file = fs.readFileSync("./abc.txt",{
encoding:'utf-8'})
console.log(file);
//异步的callback方式
fs.readFile("./abc.txt",(err,file) => {
if(err) return
console.log(file.toString('utf-8')); //默认就是utf-8
})
//异步的Promise方式
fs.promises.readFile("./abc.txt",{
encoding:'utf8'}).then(file => {
console.log(file);
})
文件的写入
const fs = require('fs')
//同步的方式
writeFile(fs.writeFileSync)
//异步的callback方式
fs.writeFile("./abc.text","文件",(err) => {
console.log("文件写入成功");
})
//异步的Promise方式
writeFile(fs.promises.writeFile)
function writeFile(fn){
let index = 0
let timer;
timer = setInterval(() => {
index++
fn("./abc.text",index+"文件\n",{flag:'a'})
}, 1000);
}
文件夹的操作
- 文件夹的操作还有很多 赋值、重命名、监听文件是否改名等等。详细看官网
- https://nodejs.org/dist/latest-v16.x/docs/api/fs.html
node中的buffer的简单了解
buffer存储的是二进制的数据,但是控制台是以16进制的方式给我们显示的
//创建bufffer
buffer.from('你好啊','utf8')
//对buffer解码 编码用那种格式 解码就要用那种 默认 utf8
buffer.toString('utf8')
//通过buffer.alloc(多少位,) 创建
Stream流
认识Stream
- 什么是流呢?
- 程序中的流也是类似的含义,我们可以想象当我们从一个文件中读取数据时,文件的二进制(字节)数据会源源不 断的被读取到我们程序中
- 而这个一连串的字节,就是我们程序中的流
- 我们可以直接通过 readFile或者 writeFile方式读写文件,为什么还需要流呢?
- 直接读写文件的方式,虽然简单,但是无法控制一些细节的操作
- 比如从什么位置开始读、读到什么位置、一次性读取多少个字节
- 读到某个位置后,暂停读取,某个时刻恢复读取等等
- 或者这个文件非常大,比如一个视频文件,一次性全部读取并不合适
文件读写的Stream
- 事实上Node中很多对象是基于流实现的:
- http模块的Request和Response对象
- process.stdout对象
- 官方:另外所有的流都是EventEmitter的实例
- Node.js中有四种基本流类型:
- Writable:可以向其写入数据的流(例如 fs.createWriteStream())。
- Readable:可以从中读取数据的流(例如 fs.createReadStream())。
- Duplex:同时为Readable和的流Writable(例如 net.Socket)。
- Transform:Duplex可以在写入和读取数据时修改或转换数据的流(例如zlib.createDeflate())
Readable
const fs = require('fs')
const read = fs.createReadStream("./text.txt",{
start:0, //文件读取开始的位置
end:3, //文件读取结束的位置
highWaterMark:1 //一次性读取字节的长度默认64kb
})
read.on("data",data => {
console.log(data.toString());
})
read.on('open',fd => {
console.log("文件被打开");
})
read.on('end', () => {
console.log('文件读取结束');
})
read.on('close',() => {
console.log('文件被关闭');
})
read.pause() //暂停流
setTimeout(() => {
read.resume() //回复
}, 1000);
Writeable
const fs = require('fs');
const {
writer } = require('repl');
const write = fs.createWriteStream('./text.txt',{
flags:"a+",
start:0, //写入开始的位置
})
write.write("你好啊11",err => {
console.log("写入成功");
})
write.on('open',fd => {
console.log("文件被打开");
})
//我们并不能监听到 close 事件,我们必须手动关闭,然后告诉Node已经写入结束了
// write.close()
//但是上边的关闭方法我们太繁琐了,我们通常是使用end方法,
//end方法相当于做了两步操作:传入的数据写入到流中和调用了close方法
write.end("写入成功")
write.on('finish',() => {
console.log('文件写入结束');
})
write.on('close',() => {
console.log('文件关闭');
})
pipe方法
const fs = require('fs');
const reader = fs.createReadStream("./text.txt");
const writer = fs.createWriteStream("./abc.txt",{
flags:'a+'
});
//使用流的方式写
reader.on('data',data => {
writer.write(data,err => {
if(err) return
console.log('写入成功');
})
})
//通过管道的方式写入
reader.pipe(writer)
http模块
创建web服务器的两种方式
const http = require('http');
// 创建server的两种方式
const server1 = http.createServer((req, res) => {
res.end("Server1")