一、什么是Node.js
1.Node.js一个基于Chrome V8引擎的 Javascript运行环境
2.Node.js中的Javascript运行环境
二、Node.js内置模块
1.fs文件系统模块
fs文件系统模块是Node.js官方提供的、用来操作文件的模块,提供了一系列的属性和方法,用于满足用户对文件的操作需求。
例如:
fs.readFile():读取指定文件中的内容
fs.writeFile():向指定文件中写入内容
要在js代码中使用fs模块来操作文件,需要先带入模块
const fs = require('fs')
1.1 fs.readFile()读取指定文件中的内容
fs.readFile()的语法格式:
fs.readFile('path',[options],callback)
//path:必选参数 文件路径
//option:可选参数 表示以什么编码格式来读取文件 utf-8
//callback:必选参数 文件读取后 通过回调函数拿到读取的结果 可以拿到读取失败和读取成功的结果
用法示例:(先创建一个txt文件保存数据:files-----a.txt)
const fs = require("fs");
fs.readFile("./files/a.txt", "utf8", function (error, res) {
console.log(error); //读取文件失败 读取成功时会得到null
console.log(res); //读取文件成功
});
结果:
可以在读取成功的时候对内容分进行操作 如:
const fs = require("fs");
fs.readFile("./files/a.txt", "utf8", function (error, res) {
// console.log(error); //读取文件失败 读取成功时会得到null
// console.log(res); //读取文件成功
// 先判断是否读取成功
if (!error) {
let str = res;
let arr1 = str.split(" "); //[ '语文-150', '数学-130', '英语-120', '物理-45', '化学-48', '生物-59' ]
arr1.map((item, index) => {
let obj = {};
let itemObj = item.split("-");
obj[itemObj[0]] = itemObj[1];
// item = JSON.parse(JSON.stringify(obj)); //直接将obj复制给item无效 要使用下标进行修改
arr1[index] = obj;
});
console.log(arr1, 222);
} else {
console.log("读取失败", error.message);
return "读取失败";
}
});
结果:
1.2 fs.writeFile() 写入文件
fs.writeFile()语法格式:
fs.writeFile('file-path','content',[options],callback)
//file-path: 必写参数 文件路径及文件名 例如:./files/fileName.txt
//content:必写参数 写入的内容
//options:可选参数 以什么格式写入文件内容 编码格式 utf-8
//callback:回调函数
const fs = require("fs");
fs.writeFile("g:./files/b.txt", "hello world 1111", "utf-8", function (error) {
console.log("写入结果 成功为null 失败打印出失败", error);
});
效果:(有b.txt文件的话 会直接修改里面的内容 没有的话会自己新建b.txt文件)
注意:只能创建文件 不能创建路径上的其他文件夹
判断文件是否写入成功:
判断error是否可以转为true 为true即写入失败 为false即为写入成功
fs.writeFile("./files/b.txt", "你好世界", function (error) {
if (error) {
console.log("写入失败", error.message);
} else {
console.log("写入成功");
}
});
练习:
有一个成绩文档,内容为:语文-150 数学-130 英语-120 物理-45 化学-48 生物-59
要求:把以上格式转为以下格式 并存在成绩-ok.txt文件中
语文:150
数学:130
英语:120
物理:45
化学:48
生物:59
const fs = require("fs");
fs.readFile("./files/成绩.txt", "utf-8", function (error, res) {
if (error) {
return console.log("读取失败");
} else {
let arr = res.split(" ");
console.log(arr);
let content = "";
arr.map((item, index) => {
arr[index] = item.replace("-", ":");
});
content = arr.join("\r\n"); //以换行进行拼接
fs.writeFile("./files/成绩-ok.txt", content, "utf-8", (error) => {
console.log(error);
});
}
});
1.3 fs路径动态拼接
使用fs模块操作文件时 使用./ 或 ../相对路径时 会出现路径顶他拼接错误:
执行node时 会根据node的当前目录来执行的
当node cd命令到其他目录下时 会以cd后的目录为参考 从cd后的开始找相对路径
解决方法:
(1).使用绝对路径 防止路径动态拼接
注意 :复制路径时 \需要进行转义 \\
缺点:移植性差 不利于维护
(2).使用 __dirname(表示当前文件所处的目录 以当前目录为参考)
优点:不会根据node的执行目录而变化 保持了移植性和维护性
其他fs的方法
操作 | 异步方法 | 同步方法 |
打开文件 | fs.open(path, flags[, mode], callback) | fs.openSync(path, flags[, mode]) |
文件信息 | fs.stat(path[, options], callback) | fs.statSync(path[, options]) |
新建文件 | fs.appendFile(path, data[, options], callback) | fs.appendFileSync(path, data[, options]) |
写入文件 | fs.writeFile(file, data[, options], callback) | fs.writeFileSync(file, data[, options]) |
读取文件 | fs.read() | |
读取文件 | fs.readFile(path[, options], callback) | fs.readFileSync(path[, options]) |
重命名文件 | fs.rename(oldPath, newPath, callback) | fs.renameSync(oldPath, newPath) |
关闭文件 | fs.close(fd, callback) | fs.closeSync(fd) |
截取文件 | fs.ftruncate(fd[, len], callback) | fs.ftruncateSync(fd[, len]) |
删除文件 | fs.unlink(path, callback) | fs.unlinkSync(path) |
文件存在 | fs.stat() / fs.access() | fs.existsSync(path) |
监听文件 | fs.watchFile(filename[, options], listener) | |
停止监听 | fs.unwatchFile(filename[, listener]) | |
打开大文件 | fs.createReadStream(path[, options]) | |
写入大文件 | fs.createWriteStream(path[, options]) | |
创建目录 | fs.mkdir(path[, options], callback) | fs.mkdirSync(path[, options]) |
读取目录 | fs.readdir(path[, options], callback) | fs.readdirSync(path[, options]) |
删除目录 | fs.rmdir(path, callback) | fs.rmdirSync(path) |
2. path路径模块
path模块时Node.js官方提供的、用于处理路径的模块,它提供了一系列的属性和方法,用于满足用户对路径的处理需求
例如:
path.jion():用来将多个路径片段拼接成一个完整的字符串
path.basename():用来从路径中将文件名解析出来
注意:要在js代码中使用path模块来处理路径,需要先进行导入
const path = require('path')
2.1 path.join()路径拼接
使用path.join可以拼接多个路径片段
语法格式:
path.join(...paths)
//...paths:表示可以传入任意的路径片段
//调用该方法会返回拼接好的路径字符串
使用示例:
const path = require("path");
// join 会把 ../会抵消前面的路径
let path1 = path.join("/a", "/b/c", "../", "./d", "e");
console.log(path1); // 输出 \a\b\d\e
let path2 = path.join(__dirname, "files", "mytext.txt");
console.log(path2, 2222); // 输出 当前文件所在目录/filed/mytext.txt
let path3 = path.join(__dirname, "./files", "./mytext.txt");
console.log(path3, 3333); //输出 当前文件所在目录/filed/mytext.txt
// 输入./ 或者直接写文件名都会直接拼接好
//但是最后一个写./ files / mytext.txt的话 mytext前面就会有两个files
2.2 path.basename() 获取路径中的文件名
使用path.basename() 可以获取路径中最后一部分,经常通过这个来获取路径中的文件名
语法格式:
const filename=path.basename(path[,ext])
//path:必选参数 路径字符串
//ext:可选参数 表示文件扩展名
//会返回路径的最后一部分
const fpath=path.basename('./files/myfile.html')
console.log(fpath)// 输出myfie.html
//传入两个参数的话 得到的是去掉后缀的文件名
const fpath1=path.basename('./files/myfile.html','.html')
console.log(fpath1)// 输出myfie
2.3 path.extname() 获取文件的扩展名
使用path.extname() 用于获取路径中的扩展名部分
语法格式:
const path = require('path')
const myname = path.extname('path')
//path为必选参数 文件的路径
const path = require("path");
const myfileextname = path.extname("files/成绩-ok.txt");
console.log(myfileextname); //输出txt
3. http模块
官网指南 https://nodejs.org/zh-cn/docs/guides/anatomy-of-an-http-transaction
管网api: http://ghttps://nodejs.org/api/http.html
http模块是官方提供的 用于创建web服务器的模块 通过http模块提供的http.createServer() 方法,就能方便的把一台普通的电脑变成一台web服务器 从而提供web资源服务
语法格式:
const http = require('http')//引入http模块
const server=http.createSrever()//创建实例
server.on('request',(request,response)=>{
const url=request.url //可以拿到请求地址 (端口以后的api地址)
const method=request.method //可以拿到请求类型 get、post
})
//使用server.on绑定request事件 回调中有两个参数 request为请求对象
server.listen(端口,callback()=>{
console.log('running at http://127.0.0.1')
})
//使用server.listen() 启动服务器
3.1 创建最基本的web服务器的基本步骤
(1)导入http模块 require('http')
(2)创建web服务器实例 http.createSrever()
(3)为服务器实例绑定request事件,监听客户端的请求
server.on('request',(request,response)=>{})
(4)启动服务器 server.listen(端口,callback(){console.log('running at http://127.0.0.1')})
3.2 request请求对象:
(1)访问地址以及请求头
通过request.url 可以拿到请求中端口后面的地址
通过request.method 可以拿到请求的类型 get 或post
通过request.header 可以拿到请求头
可以解构出来使用
const {url,method,header} = request
(2)request请求对象 : 请求体
当接受到了一个 POST
或者 PUT
请求时,请求体对于你的应用程序非常重要,我们可以通过监听 'data'
和 'end'
事件从而把 数据给取出来。
每次在 'data'
事件中触发抓获的数据块是一个 Buffer。如果你已知是一个字符串对象,那么 最好的方案就是把这些数据收集到一个数组中,然后在 'end'
事件中拼接并且把它转化为字符串。
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// at this point, `body` has the entire request body stored in it as a string
});
3.3 抛出错误
如果你不去处理监听这个事件,此错误将被抛出,这导致你的程序崩溃。
request.on('error', (err) => {
// This prints the error message and stack trace to `stderr`.
console.error(err.stack);
});
3.4 响应对象
如果服务器不发送响应对象给客户端,那么你的请求只会超时。
const http = require("http");
http.createServer((request, respond) => {
const str = `url:${request.url},method:${request.method}`;
//向客户端发送指定数据 并结束这次请求的处理过程 respond.end()
respond.end(str);
});
3.5 状态码
返回客户端的默认状态码为 200。在某些情况下要返回一个不同的状态码,可以设置 statusCode
属性。
response.statusCode = 404; // Tell the client that the resource wasn't found.
3.6 响应头
响应头通过一个setHeader的属性很方便地设置。设置响应头时,它们的名字是大小写敏感的。如果你重复设置响应头,最后一次设置的值也就是系统得到的值。
response.setHeader('Content-Type', 'application/json');
response.setHeader('X-Powered-By', 'bacon');
解决中文乱码:
res.setHeader('Content-Type', 'text/html; charset=utf-8')
整合:
基于先前的示例代码,我们将作出一个服务端,使它可以将从用户接受到的全部信息返回给用户。我们将通过JSON.stringify
对消息数据进行格式化。
const http = require('http');
http.createServer((request, response) => {
const { headers, method, url } = request;
let body = [];
request.on('error', (err) => {
console.error(err);
}).on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// BEGINNING OF NEW STUFF
response.on('error', (err) => {
console.error(err);
});
response.statusCode = 200;
response.setHeader('Content-Type', 'application/json');
// Note: the 2 lines above could be replaced with this next one:
// response.writeHead(200, {'Content-Type': 'application/json'})
const responseBody = { headers, method, url, body };
response.write(JSON.stringify(responseBody));
response.end();
// Note: the 2 lines above could be replaced with this next one:
// response.end(JSON.stringify(responseBody))
// END OF NEW STUFF
});
}).listen(8080);
简化:
让我们简化之前的代码,做一个可以有响应的简单的服务端。它同样也可以把接受到的任何信息返回给客户端。我们所要做的就是从请求流中把请求数据取出,然后原样写回到返回流中即可。就如我们之前做的那么简单。
const http = require('http');
http.createServer((request, response) => {
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
response.end(body);
});
}).listen(8080);
现在让我们调整一下,我们只对以下条件应答:
- 请求方法是 POST 方式。
- 访问路径是
/echo
。
其它任何情况均返回 404。
const http = require('http');
http.createServer((request, response) => {
if (request.method === 'POST' && request.url === '/echo') {
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
response.end(body);
});
} else {
response.statusCode = 404;
response.end();
}
}).listen(8080);