【Node.js实战】一文带你开发博客项目之日志(文件读写、stream流、写日志)

简介: 【Node.js实战】一文带你开发博客项目之日志(文件读写、stream流、写日志)

一、前言

开发日志对整个项目可以起到备忘、记录、总结等作用。以帮助开发或者运维人员快速定位错误位置,提出解决方案。


系统没有日志,就等于人没有眼睛(重要性可见一斑)

第一,访问日志 access log(server 端最重要的日志)

第二,自定义日志(包括自定义事件、错误记录等)

所以,日志的存在还是非常非常有必要的!

日志要放在文件中,可读可写~

  • node.js 文件操作,node.js stream(流 => 提升性能)
  • 日志功能开发和使用
  • 日志文件拆分,日志内容分析

二、文件的读写

1、读取文件

接下来,我们先学习如何进行文件的读取…

创建 file-test 文件夹,文件夹下创建 test1.txt 文件 和 data.txt 文件

test1.txt

进行文件读取操作,读取 data.txt 文本的内容,并进行输出

const fs = require('fs')
const path = require('path')
// 获取文件目录 __dirname 表示当前文件所在目录
const fileName = path.resolve(__dirname, 'data.txt')
// 读取文件内容(异步的)
fs.readFile(fileName, (err, data) => {
    if (err) {
        console.error(err)
        return
    }
    // data 是二进制类型,需要转成字符串类型
    console.log(data.toString())
})

data.txt

这是我们在文本中存储的一些信息

Hello
这里是前端杂货铺
感谢你的观看
Thanks

b22d8fc8636241c8a15870190a299fe0.png

2、写入文件

接下来,我们进行文件的写入操作(分为两种:追加写入和覆盖写入)

test1.js

const fs = require('fs')
const path = require('path')
// 获取文件目录 __dirname 表示当前文件所在目录
const fileName = path.resolve(__dirname, 'data.txt')
// 写入文件
const content = '哇咔咔,这是新写入的内容\n'
// 写入的方式(追加'a'/覆盖'w')
const opt = {
    flag: 'a' // 追加写入用'a',覆盖用 'w'
}
// 写入文件(文件名,内容,方式,错误的回调)
fs.writeFile(fileName, content, opt, err => {
    if (err) {
        console.error(err)
    }
})

终端运行 node test1.js

d9eef46f942641d48701fc5f0f49e99b.png

3、判断文件是否存在

接下来,我们来进行判断文件是否存在的操作

test1.js

const fs = require('fs')
const path = require('path')
// 获取文件目录 __dirname 表示当前文件所在目录
const fileName = path.resolve(__dirname, 'data.txt')
// 判断文件是否存在
fs.exists(fileName, (exist) => {
    console.log('exist', exist)
})

d4e3d6c409614c82a03f0df6b640dce8.png

三、stream 流

1、IO 操作的性能瓶颈

IO 包括 “网络IO” 和 “文件IO”

相比于 CPU 计算和内存读写,IO 的突出特点就是慢!

我们需要在有限的硬件资源下提高 IO 的操作效率!!

那么我们就要使用 stream 流(不是一下子全给,而是通过“小管子”一点点给…)

bdc01fea31bf4db1b71da4b2b2a5a332.png

2、stream 流

在 stream-test 文件夹下创建 test1.js 文件

test1.js

// 标准输入输出
process.stdin.pipe(process.stdout)

279cd9e6a0cd4cdd9812912fccab86a9.png

下面我们监听端口,通过 postman 进行简单测试

test1.js

const http = require('http')
const server = http.createServer((req, res) => {
    if (req.method === 'POST') {
        // 管道连接请求和响应
        req.pipe(res)
    }
})
// 监听的端口 8000
server.listen(8000)

终端 node test1.js 启动它,之后去 postman 进行测试

30f21fdaa1e849d08ab9ce12b91c1e71.png

3、复制文件

我们先创建 stream-test 文件,之后创建文本(原文本和复制的目标文本,之后在 test1.js 中添加一些代码),此时 data.txt 文本有内容,data-bak.txt 文本为空。

ac07a1b2b75242d3a23d0bb4256fcf78.png

data.txt

这里是前端杂货铺
当前目标如下:
把 data.txt 文本里的内容拷贝到 data-bak.txt 中

test1.js

// 复制文件
const fs = require('fs')
const path = require('path')
const fileName1 = path.resolve(__dirname, 'data.txt')
const fileName2 = path.resolve(__dirname, 'data-bak.txt')
// 读取流
const readStream = fs.createReadStream(fileName1)
// 写入流
const writeStream = fs.createWriteStream(fileName2)
// 管道连接
readStream.pipe(writeStream)
// 监听每一次读取的内容
readStream.on('data', chunk => {
    console.log(chunk.toString())
})
// 监听拷贝完成
readStream.on('end', () => {
    console.log('copy done')
})

3712bba6de1c4e148d8079b9859b07c2.png

48387b0127514d5e8bcda1be089d3581.png

4、发起请求读取文件

发送一个 GET 请求,读取文本的内容

test.js

const http = require('http')
const fs = require('fs')
const path = require('path')
const fileName1 = path.resolve(__dirname, 'data.txt')
const server = http.createServer((req, res) => {
    if (req.method === 'GET') {
        const readStream = fs.createReadStream(fileName1)
        // 将 res 作为 stream 的 dest
        readStream.pipe(res)
    }
})
// 监听的端口 8000
server.listen(8000)

终端 node test1.js 运行,之后打开 8000 端口

825d79afef3a40f485e2813dffce7c41.png

四、写日志

我们首先改变一下我们的目录结构(新增如下文件)

logs 里面的文件用来存放写入的日志(创建空文件就好),utils 里面的 log.js 文件用来编写一些写入日志的逻辑

8b206c74ce1a4b1ca7e97ccfd0a8dcbf.png

og.js

首先我们引入所需模块,封装写入流函数,访问我们所需的日志,进行换行写入

// 引入 fs 和 path 模块
const fs = require('fs')
const path = require('path')
// 写日志
function writeLog(writeStream, log) {
    // 关键代码(每写入一行日志换行一次)
    writeStream.write(log + '\n')
}
// 生成 write Stream(第二个水桶)
function createWriteStream(fileName) {
    // 找到文件名
    const fullFileName = path.join(__dirname, '../', '../', 'logs', fileName)
    // 创建写入流(追加的方式)
    const writeStream = fs.createWriteStream(fullFileName, {
        flags: 'a'
    })
    // 返回写入的内容
    return writeStream
}
// 写访问日志
const accessWriteStream = createWriteStream('access.log')
// 参数 log 为 app.js 中传入的内容
function access(log) {
    writeLog(accessWriteStream, log)
}
module.exports = {
    access
}

之后更改 app.js 文件,调用 access 函数

app.js

我们先导入 access 进来,之后进行调用,传进所需的参数,用来记录 access log

const { access } = require('./src/utils/log')
...
const serverHandle = (req, res) => {
    // 记录 access log
    access(`${req.method} -- ${req.url} -- ${req.headers['user-agent']} -- ${Date.now()}`)
    ......
}

之后,我们打开 http://localhost:8000/api/blog/list 端口,进行三次刷新,查看 access.log 文件中日志的写入

13a49efb1f574789997efbc4341b34e4.png

五、写在最后

至此,我们明白了 如何进行文件读写,了解了 stream流 的原理及其基本使用,以及如何写日志。 继续跟进学习吧!


后续会对该项目进行多次重构【多种框架(express,koa)和数据库(mysql,sequelize,mongodb)】


如果你需要该项目的 源码,请通过本篇文章最下面的方式 加入 进来~~

45fc82a82c6542bdb2ff4986377d8db3.png

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
661 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
10月前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
390 1
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
监控 安全 中间件
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
这篇文章介绍了什么是Next.js中的中间件以及其应用场景。中间件可以用于处理每个传入请求,比如实现日志记录、身份验证、重定向、CORS配置等功能。文章还提供了一个身份验证中间件的示例代码,以及如何使用限流中间件来限制同一IP地址的请求次数。中间件相当于一个构建模块,能够简化HTTP请求的预处理和后处理,提高代码的可维护性,有助于创建快速、安全和用户友好的Web体验。
472 0
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
484 2
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
367 1
JavaScript中的原型 保姆级文章一文搞懂
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
247 0
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
623 5
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
471 4