一.完整的软件系统
我们平时经常会使用一些APP或者网页,但是其实这些只是一个软件系统的一部分,在软件系统中服务端至关重要,无论我们使用的是Android还是IOS其实数据都不是存储在我们手机上的,而是存储在服务器的数据库中的,由服务端语言去操作查询返回给客户端,常见的服务端语言或者运行时环境有:Java
Golang
Node.js
等等,如下就是一个完整的软件系统。
二.为什么推荐Node
对于前端技术人员而言对于服务端的学习首先推荐学习Node开发服务器,Node优点有很多。
- 一方面Node在服务器端的性能是比较高的。
- 对于一个前端开发而言去学习Java需要学习的内容是比较多的。
- 如果在后续想要学习SSR相关的知识,其实是离不开Node的。
- 使用相同的语言,前后端一体化,使用TypeScript甚至可以共享类型。
三.什么是Node.js
😃Node.js是一个基于V8引擎的JavaScript运行环境,也就是说Node是基于V8引擎来运行执行JavaScript代码的,但是不仅仅有V8引擎,Node中和Chorme在架构方面也有很大的差异,因为在浏览器中需要解析和渲染HTML,CSS等内容,另外还要支持浏览器操作的API,并且实现自己的事件循环。
🥹在Node中我们相对于浏览器中需要其他另外的操作,比如文件的读写,网络IO,加密,压缩解压文件。
四.Node.js架构
Node关键组件叫做LIBUV
是一个由C语言编写的库,libuv提供了事件循环、文件系统读写、网络IO、线程池等等内容,以下是Node的JavaScript执行过程。
Application
模块就是我们编写的JavaScript代码,在Node中交由V8引擎执行。V8 Engine
经过V8引擎的执行的JavaScript代码,然后通过Node.js Bindings与LIBUV进行交互。Event Queue
经过Node.js Bindings系统操作后进入事件队列,然后进行事件循环。- 任务经过事件循环然后对应的执行相应的工作线程
worker Threads
向操作系统内核执行调用。 - 当相应的任务执行完毕后会返回结果,返回的结果会通过回调函数一级一级的返回,就可以拿到数据了。
五.内置模块fs之文件读取
😃fs
全称是文件系统,在服务端中的大多数操作就是从数据库中读取数据然后对数据进行处理,处理完之后返回给前端,其实Node之所以能够做服务端应用程序很大的一点就是因为有文件系统,同时所有的后端编程语言都有自己的文件系统,文件系统大致上做的是如下这样的一个操作过程。
借助于Node帮我们封装的文件系统,我们可以在任何操作系统上面直接去操作文件,这也是它可以成为前端自动化脚本等热门工具的原因。
fs模块的API非常多,我们不可能也没有必要全部学习,在学习阶段我们只需要学习常用的即可,其他内容在开发中遇到的时候再去查询即可,Node文件系统的API大致分为三种:
- 同步操作文件,代码会被阻塞,不会继续执行。
- 异步回调函数操作文件,代码不会被阻塞,需要传入回调函数,当获取到结果时,回调函数执行。
- 异步Promise操作文件,代码不会被阻塞,通过
fs.promises
调用方法操作,会返回一个Promise,可以通过then和catch进行操作。
😃同步读取文件:
js
const fs = require("fs")
let text = fs.readFileSync("./test.txt", {
encoding:
})
console.log(text)
🥹异步回调函数的读取方式:
js
const fs = require("fs")
fs.readFile("./test.txt", "utf-8", (err, res) => {
if (err) {
console.log("文件读取错误", err)
} else {
console.log(res)
}
})
👽异步Promise的读取方式:
js
const fs = require("fs")
fs.promises.readFile("./test.txt", {
encoding: 'utf-8'
}).then((res) => {
console.log(res)
}).catch((err) => {
console.log("文件读取报错", err)
})
六.文件描述符
在常见的操作系统上,对于每个进程,内核都维护着一张当前打开的文件和资源表格,每个打开的文件都会分配一个称之为文件描述符的简单的数字表示符,在系统层,所有的文件系统都使用这些文件描述符来标识和跟踪每个特定的文件,Window系统使用了一个虽然不同但是概念上类似的机制来跟踪资源。
js
const fs = require("fs")
fs.open("./test.txt", (err, fd) => {
if (err) {
console.log("文件打开失败")
} else {
console.log(fd)
}
})
通过上述的内容就可以获取到文件描述符,然后通过文件描述符我们就可以直接进行对应文件的操作,比如我可以使用文件描述符来进行文件的写入操作。
js
const fs = require("fs")
fs.open("./test.txt", (err, fd) => {
if (err) {
console.log("文件打开失败")
} else {
const content = "Hello World!!!"
fs.writeFile("./test.txt", content, (err, data) => {
if (err) {
console.log(err)
} else {
console.log("文件写入成功")
}
})
}
})
我们也可以通过文件描述符来获取当前文件的信息。
js
const fs = require("fs")
fs.open("./test.txt", (err, fd) => {
if (err) {
console.log("文件打开失败")
} else {
const content = "Hello World!!!"
fs.fstat(fd, (err, data) => {
if (err) {
console.log("获取文件信息失败")
} else {
console.log(data)
}
})
}
})
然后我们就可以打印出下面的这些内容,也就是当前文件的基本信息。
七.内置模块fs之文件写入
我们模拟一个场景,客户端传递过来一段数据,这个时候我们需要将这些内容写入到服务器的某个文件,这个时候我们应该怎么做哪?其实无论再什么语言中我们的做法基本上都是一样的,就是使用对应语言的文件系统来将获取的内容进行写入。
js
const fs = require("fs")
const content = "这是一首简单的歌~"
fs.writeFile("./test.js", content, { flag: 'a+' }, (err,data)=> {
if (err) {
console.log("文件写入错误")
}else{
console.log("文件写入成功")
}
})
如上代码就是Node文件系统的写入方式,和读取方式一样Node的写入方式也分为三类,分别是同步读取,异步回调读取和异步Promise方式的读取,上面我们使用的是异步回调函数的写入方式,我们分别来演示下其余的两种
js
// 同步读取
const fs = require("fs")
const content = "这是一首悲伤的歌~"
let data = fs.writeFileSync("./test.txt", content, {
flag: "w",
encoding: "utf-8"
})
console.log(data)
另外一种就是Promise的读取方式。
js
const fs = require("fs")
const content = "这是一首欢乐的歌~"
fs.promises.writeFile("./test.txt", content, {
flag: 'a+',
encoding: 'utf-8'
}).then((res) => {
console.log(res)
}).catch((err) => {
console.log("文件写入错误", err)
})
😃在上述的文件写入中你可能会发现有个特别的option
这个选项中分别是encoding
和flag
这两个参数分别指代的意思是编码方式,我们一般指定的都是utf-8
编码和对文件操作方式的限制,flag
的值有很多但是我们平时使用的有以下几种。
- w:打开文件写入,默认值。
- w+:打开文件进行读写,可读可写,如果文件不存在则创建文件。
- r:打开文件进行读取,读取时候的默认值。
- r+:打开文件进行读写,如果文件不存在则抛出默认值。
- a:打开要写入的文件,把流放在文件的末尾,如果不存在则创建文件。
- a+:打开文件进行读写,可读可写,将流放在文件末尾,不存在则创建文件。
八.总结
💡本章节我们主要讲解了一个完整的软件系统是什么样的,以及它包含的几部分,服务端,Web端,客户端,桌面端等等,其中服务端是一个软件系统的核心组成部分,为客户端和Web端等前端部分提供数据。然后我们介绍了为什么作为一个前端开发为什么需要学习Node而不是从头去学习一门其他的编程语言,当然掌握更多的语言当然是好的,但是相对而言掌握Node的性价比更加的高,直接可以前后端一体化开发。之后我们就开始介绍Node的基础架构以及node中一个重要的模块LIBUV,它是使用C语言编写的,实现了很多Node需要的功能。接下来就是本章节的主要内容,node的文件系统,我们从更高的视角讲解了文件系统基本API的三种用法,分别是,异步回调的方式,异步Promise的方式,同步方式,并且学习了文件系统读写的API,以及常用的编码方式,和常用的几个选项,当然文件系统关于读写的API还有很多,但是这些是比较常用的,其他我们在开发中用到可以具体的去学习,下一个章节我们将学习文件系统对文件夹的读写以及递归操作,敬请期待~