【Node.js】笔记整理 2 - 常用模块

写在最前:跟着视频学习只是为了在新手期快速入门。想要学习全面、进阶的知识,需要格外注重实战和官方技术文档,文档建议作为手册使用

系列文章

1、 fs —— 文件模块

fs模块提供了对文件、文件夹操作的能力。在这个模块中,写入的数据如果想要换行,需要使用\r\n,而不是\n

另外请注意,读取到的都是Buffer,你需要按照文件的格式选择对应的方法将其转化为需要的数据,比如读取txt文件,你可以使用toString()进行转换

引入fs模块

const fs = require('fs')

文件写入

需要持久化保持数据时,除了直接存储在数据库,还有可以利用文件写入

writeFile - 异步写入文件

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

  • file: 写入的文件名
  • data: 写入文件的数据
  • options: 写入时给文件的选项配置
  • callback: 写入文件后的回调函数

示例:

const fs = require('fs')

fs.writeFile('./hello.js', 'console.log('hello node')', (res) => {
    console.log(res)
    // 写入失败则res 为 Error对象, 成功则为null
})
weiteFileSync - 同步写入文件

语法:fs.writeFileSync(file, data[, options]), 注意没有回调函数

fs.writeFile('./hello.js', 'console.log('hello nodeSync')')
appendFile / appendFileSync —— 追加写入

追加写入时在指定文件末尾添加内容

语法: fs.appendFile(file, data[, options], callback)fs.appendFileSync(file, data[, options])

二者返回undefined

createWriteStream - 流式写入

优势:可以减少打开关闭文件的次数,适合大文件写入或者频繁写入,流式写入可以在这种场景下提高性能

语法: fs.createWriteStream(path[, options])

  • path:文件路径
  • options:选项配置

返回值:Object

使用流式写入时,需要先和文件建立通道: const ws = createWriteStream('filePath')

然后可以使用ws.wirte(data)写入内容,文件内容写入完毕后,使用ws.close()关闭通道,通道关闭前都可以向对应文件中写入数据

const ws = fs.createWriteStream('filePath')

// 流式写入数据
ws.write('hello world\r\n')

// 关闭通道
ws.close()

读取文件

当需要读外部文件获取信息时候都要进行文件读取,比如读音乐、读视频、读系统文件等等

readFile - 异步读取

语法:fs.readFile(path[, options], callback(err, data))

返回值:undefined

读取到的data是一个Buffer,需要进行处理

const fs = require('fs')

fs.readFile('./hello.js', (err, data) => {
    if(err){
        // ...
    }
    
    // 读取到的是Buffer, 还需要转字符串
    if(data){
        data = data.toString()
    }
})

readFileSync - 同步读取

语法: fs.readFileSync(path[, options])

返回值: Buffer,读取结果

const fs = require('fs')

let data = fs.readFileSync('./hello.js')
const fileInfo = data.toString()

createReadStream - 流式读取

同样的你需要建立一个通道, 创建读取流对象: const rs = fs.createReadStream(path[, options], callback)

  • 获取读取到的数据: rs.on('data', (chunk) => {}),绑定data事件, chunk是流式读取时每次读取到的Buffer块,通过length属性可以获取每个块的字节大小
  • 读取完毕时可触发回调:rs.on('end', () => {}),绑定end事件

fs模块实例

流式复制文件

非流式就是读完了然后写进一个新的,操作都简单就不用说了,这里主要记流式,边读边写。流式也是经常使用的方式,因为更适合读大文件的情景。并且对资源的利用更优

const rs = fs.createReadStream('./hello.js')
const ws = fs.createWriteStream('./hello_copy.js')

rs.on('data', chunk => {
    ws.write(chunk)
})

rs.on('end', () => {
    alert('文件复制完毕')
})

管道快速复制文件(不大的):

rs.pipe(ws)

文件重命名和移动

要用到fs模块提供的rename()API

语法:fs.rename(path, newPath, callback(err))

同步版本: fs.renameSync(path, newPath)

const fs = require('fs')

fs.rename('./hello.js', './newName.js', err => {
    if(err){
        //...
    }else{
        //...
    }
})

通过上面的例子可以看到,这个API也可以用于移动文件

文件删除

要用到fs模块提供的unlinkunlinkSync

语法:unlink( path, callback(err) )

同步版类推

代码示例省略

node 14.4版本引入了新的删除文件API —— rmrmSync

语法:fs.rm( path. callback(err) )

文件夹操作
API功能
mkdir、mkdirSync创建文件夹
readdir、readdirSync读取文件夹
rmdir、rmdirSync (这两个api将来会被移除)、rm(建议使用)删除文件夹

1、创建文件夹

和linux命令名一样是mkdir

语法: fs.mkdir( path[, options], callback(err) )

const fs = requrie('fs')

fs.mkdir('./newFile.txt', err => {
    // ...
})


// 递归创建
fs.mkdir('./a/b/c', { recursive: true }, err => {
    // ...
}

2、文件夹读取

语法:fs.readdir( path, callback( err, data ) )

fs.readdier('./hello.js', (err, data) => {
	if(err){
        //...
    }
    
    // 处理读取结果data
})

3、删除文件夹

语法:fs.rm( path, callback(err) )

递归删除: fs.rm( path, { } )

fs.rm('./a', { recursive: true }, err => {
    //...
})

查看文件资源状态

语法: fs.state( path, [, options], callback(err, data) )、同步版本fs.stateSync

data结构:

  • size: 文件体积
  • birthtime:创建时间
  • mtime:最后修改时间
  • isFile:检测是否为文件
  • isDirectory:检测是否为文件夹

会用到的全局变量:

  • __dirname:可以获取其所在文件的所在目录的绝对路径,这可以避免工作目录变化的影响。
  • __filename:当前文件的绝对路径

2、path —— 路径模块

常用API:

API功能
path.resolve拼接规范的绝对路径
path.sep获取操作系统的路径分隔符
path.parse( filePath )解析路径并返回对象
path.basename( filePath )获取路径的基础名称
path.dirname( filePath )获取路径的目录名
path.extname( filePath )获取路径的扩展名

path.resolve —— 路径拼接

语法: path.resolve( 绝对路径, 相对路径 )

const path = require('path')

let filePath = path.resolve(__dirname, './hello.js')
let filePath = path.resolve(__dirname, 'hello.js')  // 不写./也可以

path.sep —— 获取当前操作系统的路径分隔符

语法: path.sep

区别: window下返回值是\,Linux下结果是/

path.parse —— 解析路径

语法: path.parse( filePath )

返回值是一个Object:

  • root:根
  • dir:文件夹路径
  • base:文件
  • ext:文件类型
  • name:文件名

3、Http

Http报文相关在AJAX基础已经学了这里省略

IP和端口

去看计网

http模块

从这里开始,就是后端基础了,node后端需要借助这个http模块进行

const http = require('http')

http.createServer —— 创建http服务对象

语法: http.createServer( (request, response) => {} )

参数:

  • resquest:请求报文内容,包含请求体
  • response:响应报文, 对请求的响应信息在这里面进行配置
const server = http.createServer( (res, req) => {
    // ...
    response.end('响应结束')
} )

响应内容中文乱码的解决

在请求头中规定文本类型

const server = http.createServer( (res, req) => {
    // 设置接受的文本类型
    response.setHeader('Content-Type', 'text/html; charset=utf-8')
    
    response.end('响应结束')
} )

server.listen —— 监听

语法: server.listen( port, callback )

参数:

  • post: 端口号
  • callback:启动监听服务成功时的回调

http协议默认端口是80, https协议的默认端口是443,http服务开发常用端口有3000、8080、8090、9000等

获取请求体的相关数据

解义获取语法
method - 请求方法request.method
httpVersion - http协议版本号request.httpVersion
url - 请求路径request.url
url路径request(‘url’).parse(request.url).pathname
url查询字符串, 以此可以获取query参数request(‘url’).parse(request.url, true).query
header - 请求头request.headers
data - 请求体request.on(‘data’, (chunk) => {})、request.on(‘end’, ()=>{})

获取请求体的流程

const url = require('url')
const server = http.createServer( (req, res) => {
    // 获取请求方法
	let { method } = req
    // 解析url
    let resUrl = new URL(req.url , ip)
    let pathName = resUrl.pathname
    let query = res.query
    let body = ''
    
    // ... 
    request.on('data', (chunk) => {
        body += chunk
    })
    
    request.on('end', () => {
        console.log(body)
        
        // 响应
        response.end(body)
    })
} )

设置http相应报文

作用语法
code - 设置响应状态码response.statusCode
message - 设置响应状态描述response.statusMessage
header - 响应头信息response.setHeader(‘头名’, ‘头值’)
data - 响应体,即后端返回给前端的前台需要的数据response.write(data)
response.end(‘end’)

对接过后端的应该可以很清晰看出来都是些什么作用,所以就直接写示例了

const server = http.createServer( (req, res) => {
    // ... 根据一些情况进行处理并设置状态码、message、header等信息
    if(xxxxx){
        response.statusCode == xxxx
        response.statusMessage = 'xxxxx'
        response.setHeader('Content-Type': ['yyyy', 'qqqq'])
    }
    
    // ...
    // 设置响应体
    response.write(yourData)
    // ...
    request.on('data', (chunk) => {
        body += chunk
    })

    // ....
    response.end()
} )

网页资源加载过程

网页引入外部资源

静态与动态资源

搭建静态资源服务

网页URL的使用

mime类型

媒体类型mime是一种标准,用来表示文档、文件或者字节流的性质和格式

HTTP服务可以设置响应头Conent-Type来表示响应体的MIME类型,浏览器会根据该类型决定如何处理资源

常见文件的mime类型

文件类型对应mime类型
htmltext/html
csstext/css
jstext/javascript
pngimage/png
jpgimage/jpeg
gifimage/gif
mp4vidio/mp4
mp3audio/mpeg
jsonapplication/json

对于未知的资源类型,可以使用application/octet-stream类型,浏览器在遇到该类型的响应时,会对响应体内容进行独立存储

乱码问题

headers里面设置字符集编码utf-8

错误处理

对err.code进行switch case

GET 和 POST 的场景以及区别

GET请求使用场景:

  • 在地址栏输入url访问
  • 点击a标签
  • <link>标签引入css
  • <script>标签引入js
  • <video>和<audio>引入多媒体
  • <img>标签引入图片
  • <form>标签中的method为get
  • AJAX中的get请求

POST请求的情况

  • <form>标签中的method为post
  • AJAX中的post请求

区别

  • 作用:GET请求用来获取数据,POST请求用来提交数据
  • 参数位置:GET请求的参数是拼接在URL之后,而POST是参数放在请求体data
  • 安全性:POST请求相对更安全,因为参数不会暴露在url里
  • GET请求大小一般限制为2k,POST请求没有大小限制

模块化

类比组件思维,就是为了高内聚低耦合,提高复用性和可维护性,防止命名冲突

在node.js中,导入模块或者文件要使用require()

模块化示例如下:

// 暴露模块
// ./test.js
function sendCoursesList(){
    // ...
}

// 模块暴露单个数据
modules.exports = sendCoursesList

// ./index.js中导入模块
const sendCoursesList = require('./test.js')
sendCoursesList()

模块暴露对象写法:还是以上面为例

// ./test.js
modules.exports = {
    sendCoursesList,
    fn1,
    // ...
    fn2: getList()
}

// ./index.js
const test = require('./test.js')

test.getList()

模块暴露变量:下面是例子

// ./test.js
exports.fn1 = sendCoursesList

// ./index.js
const test = require('./test.js')
test.fn1()
  • modules.export可以暴露任意数据
  • 不可以使用exports = value的形式暴露数据,模块内部存在module与exports的隐式关系:exports = modules.exports = {}
  • 根据上面那条,导入后得到的是一个对象

CommonJS模块化规范

以上的module.exportsexportsrequire都是CommonJS规范中的内容,Node.js的编写要遵从CommonJS模块化规范,这就像JS和ECMAScript规范一样

有关CommonJSESM的区别,后面会专门出一篇文章总结,这里占个坑

  • 18
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六时二一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值