node、koa、express随笔

本文详细介绍了Node.js的基础知识,包括process全局对象、内置模块如path和fs,以及Buffer和Stream流。深入讲解了Express和Koa框架的中间件机制、路由使用和文件上传。此外,还探讨了Node.js操作数据库,特别是MySQL的使用,以及项目部署和问题解决。
摘要由CSDN通过智能技术生成

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")
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值