速通NodeJS基础知识——http/url/fs等内置模块
本文旨在结合代码案例总结了
NodeJS
常见内置模块的使用,包括:模块规范、url、querystring、http、event、fs、zlib以及crypto库
。
一、模块规范
CommonJS
和ESModule
都是用于在JavaScript
中组织和导入/导出代码的规范,它们的主要区别在于实现和用途。
1-CommonJS
CommonJS
是使用require()
函数来加载依赖模块,使用module.exports
对象来导出模块,具有以下特点:
- 同步加载模块
- 运行时加载
- 导出是复制一个值的引用
// 导出模块
module.exports = {
foo: 'hello',
bar: () => console.log('world')
};
// 导入模块
const module = require('./module');
module.bar; // world
2-ESModule
使用import
语句来导入模块,使用export
语句来导出模块;
在导入export
时,需要通过大括号{}
指定所需变量名称;
而在导入export default
时,则不需要使用大括号。具有以下特点:
- 异步加载模块,可以并行加载多个模块
- 编译时加载,可以进行静态分析和优化。
- 导出是一种动态连接,可以实现更灵活的代码组织和依赖管理。
// 导出模块
export const foo = 'hello';
export function bar() {
console.log('world');
}
export default () => console.log('default');
// 导入模块
import { foo, bar } from './module';
import defaultFunc from './module';
console.log(foo); // 'hello'
bar(); // 'world'
defaultFunc(); // 'default'
二、url
url库可以用于处理和解析 URL
const url = require('url');
1、parse
将 URL 字符串解析为 URL 对象
url.parse(urlString[, parseQueryString[, slashesDenoteHost]])
其中,urlString
是要解析的URL字符串,parseQueryString
指定是否要将查询参数解析为一个对象,默认为false
;slashesDenoteHost
指定如果没有提供协议,是否将双斜杠视为主机名的一部分,默认为false
。
2、format
url.format(urlObject)
: 将 URL 对象转换为 URL 字符串。
3、resolve
url.resolve(from, to)
: 从基础 URL 和相对 URL 中计算出目标 URL。
4、URL
这是一个全局类,在 Node.js v10.0.0 版本中引入
new URL(input[, base])
: 创建一个新的 URL 对象。
虽然 URL 是一个全局类,但在编写 Node.js 应用程序时,最好还是显式地导入 URL 类,以便代码更加清晰和易于维护。
const { URL } = require('url')
;
三、querystring
querystring库可以用于处理和解析 URL中的query参数
var str = "name=zhangsan&age=10&height=170";
var querystring = require("querystring");
var obj = querystring.parse(str);
1、parse
querystring.parse(str[, sep[, eq[, options]]])
: 将 URL 查询字符串解析为 JavaScript 对象。参数 sep 和 eq 分别指定分隔符和赋值符号,默认值为 & 和 =。。
2、stringify
querystring.stringify(obj[, sep[, eq[, options]]])
: 将 JavaScript 对象序列化为 URL 查询字符串。参数 sep 和 eq 分别指定分隔符和赋值符号,默认值为 & 和 =。
3、escape
querystring.escape(str)
: 对给定的字符串进行 URL 编码,使其在 URL 查询字符串中能够安全使用。
4、unescape
querystring.unescape(str)
: 对已编码的字符串进行解码。
四、http
1、server
创建服务器
const http = require("http");
const server = http.createServer();
server.on("request", (req, res) => {
// req 接受浏览器传的参数
// res 返回渲染内容
});
server.listen(3000, () => {
console.log("server start!");
});
2、jsonp
JSONP(JSON with Padding)是一种跨域通信的解决方案,它利用了 HTML 中 script 标签可以跨域加载数据的特性来实现。在使用 JSONP 方案时,服务器端需要将数据包装成一个 JavaScript 函数返回给客户端调用。
下面是一个简单的案例
浏览器端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jsonp</title>
</head>
<body>
<script>
var oscript = document.createElement('script')
oscript.src = 'http://localhost:3000?callback=stars'
document.body.appendChild(oscript)
function stars(obj) {
console.log(obj);
}
</script>
</body>
</html>
node服务端
var http = require("http");
var url = require("url");
http
.createServer((req, res) => {
const myUrl = url.parse(req.url, true);
res.end(
`${myUrl.query.callback}(${JSON.stringify({
name: "stars",
age: 20,
})})`
);
})
.listen(3000, () => {
console.log("server star");
});
3、CORS
CORS(Cross-Origin Resource Sharing)是一种跨域资源共享的解决方案,可以让浏览器在安全的前提下,实现从一个源站点向另一个站点发起跨域请求。CORS 的原理基于以下几个步骤:
- 客户端发送跨域请求时,会在请求头中加入 Origin 字段,该字段表示当前页面的源地址。
- 服务端接收到请求后,根据 Origin 字段判断请求是否来自合法的源站点。
- 如果请求来自合法的源站点,则服务端需要在响应头中添加 Access-Control-Allow-Origin 字段,并将其值设置为客户端请求中的源地址或 *。这样客户端就能够通过检查响应头信息,判断该请求是否被允许。
- 此外,服务端还可以在响应头中添加其他的 CORS 头信息,如 Access-Control-Allow-Methods、Access-Control-Allow-Headers 等,以指定允许的请求方法、请求头信息等内容。
浏览器端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cors</title>
</head>
<body>
<script>
fetch("http://localhost:3000/api/aaa").then(res => res.json()).then(res => {
console.log(res);
})
</script>
</body>
</html>
服务器端
var http = require("http");
var url = require("url");
http
.createServer((req, res) => {
const myUrl = url.parse(req.url, true);
res.writeHead(200, {
"Content-Type": "application/json;charset=utf-8",
// cors头
"access-control-allow-origin": "*",
});
switch (myUrl.pathname) {
case "/api/aaa":
res.end(
`${JSON.stringify({
name: "stars",
age: 20,
})}`
);
break;
default:
res.end("404");
}
})
.listen(3000);
4、get
直接上案例
发起请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>get请求</title>
</head>
<body>
<script>
fetch("http://localhost:3000/api/aaa").then(res => res.json()).then(res => {
console.log(res);
})
</script>
</body>
</html>
响应请求
var http = require("http");
var https = require("https");
var url = require("url");
http
.createServer((req, res) => {
const myUrl = url.parse(req.url, true);
res.writeHead(200, {
"Content-Type": "application/json;charset=utf-8",
// cors头
"access-control-allow-origin": "*",
});
switch (myUrl.pathname) {
case "/api/aaa":
httpGet((data) => {
res.end(data);
});
break;
default:
res.end("404");
}
})
.listen(3000);
function httpGet(callback) {
var data = "";
https.get(
"https://i.maoyan.com/api/mmdb/movie/v3/list/hot.json?ct=%E6%B7%B1%E5%9C%B3&ci=30&channelId=4",
(res) => {
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
callback(data);
});
}
);
}
5、post
直接上案例
发起请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>post请求</title>
</head>
<body>
<script>
fetch("http://localhost:3000/api/aaa").then(res => res.json()).then(res => {
console.log(res);
})
</script>
</body>
</html>
响应请求
var http = require("http")
var https = require("https");
var url = require("url");
http
.createServer((req, res) => {
const myUrl = url.parse(req.url, true);
res.writeHead(200, {
"Content-Type": "application/json;charset=utf-8",
// cors头
"access-control-allow-origin": "*",
});
switch (myUrl.pathname) {
case "/api/aaa":
httpPost((data) => {
res.end(data);
});
break;
default:
res.end("404");
}
})
.listen(3000);
function httpPost(callback) {
var data = "";
var options = {
hostname: "m.xiaomiyoupin.com",
post: "443",
path: "/mtop/market/search/placeHolder",
method: "post",
headers: {
"Content-Type": "application/json",
},
};
var req = https.request(options, (res) => {
res.on("data", (chunk) => {
data += chunk;
});
res.on("end", () => {
callback(data);
});
});
req.write(JSON.stringify([{}, { baseParam: { ypClient: 1 } }]));
req.end();
}
五、event
在 Node.js 中,事件(Event)是一种基本的异步编程模型,通过触发事件和监听事件来实现不同模块之间的通信
const EventEmitter = require("events");
const event = new EventEmitter();
event.on("play", (arg1, arg2) => {
console.log("事件触发了", arg1, arg2);
});
event.emit("play", "arg1", "arg2");
六、fs
在 Node.js 中,fs(File System)模块提供了对文件和目录进行读写操作的 API。使用 fs 模块可以轻松地进行文件操作,例如创建文件、删除文件、读取文件内容、写入文件内容等。
// 新建文件夹
fs.mkdir("./file", (err) => {
if (err && err.code === "EEXIST") {
console.log("文件已存在,创建文件失败");
}
});
// 重命名文件
fs.rename("./file3", "./file2", (err) => {
if (err && err.code === "ENOENT") {
console.log("目录不存在,重命名文件失败");
}
});
// 删除文件夹,需要保证目录为空
fs.rmdir("./file2", (err) => {
if (err && err.code === "ENOENT") {
console.log("目录不存在,删除文件失败");
}
});
// writeFile,写文件,若存在,直接覆盖
fs.writeFile("./file/test.txt", "hello world", (err) => {
console.log("writeFile", err);
});
// appendFile,追加文件内容,若不存在,新建文件
fs.appendFile("./file/test2.txt", "test", (err) => {
console.log("appendFile", err);
});
// readFile,读取文件内容
fs.readFile("./file/test.txt", "utf-8", (err, data) => {
if (!err) {
console.log("readFile", data);
}
});
// unlink,删除文件内容
fs.unlink("./file/detele.txt", (err) => {
console.log("unlink", err);
});
// readdir,读取目录结构
fs.readdir("./file", (err, data) => {
if (!err) {
console.log("readdir", data);
}
});
// stat,判断是文件还是文件夹
fs.stat("./file", (err, data) => {
if (!err) {
console.log("stat1", data.isDirectory());
console.log("stat2", data.isFile());
}
});
// 可读流
const fs = require("fs");
const read = fs.createReadStream("./file/test.txt", "utf-8");
read.on("data", (chunk) => {
console.log("---", chunk);
});
read.on("end", () => {
console.log("end");
});
read.on("error", (err) => {
console.log("err", err);
});
const write = fs.createWriteStream("./file/test1.txt", "utf-8");
write.write("hello world");
write.write("你好");
write.end();
const write2 = fs.createWriteStream("./file/test2.txt", "utf-8");
read.pipe(write2);
七、zlib
使用 zlib 模块,可以轻松地进行数据压缩和解压缩操作
const http = require("http");
const fs = require("fs");
const zlib = require("zlib");
const gzip = zlib.createGzip();
http
.createServer((req, res) => {
const readStream = fs.createReadStream("./test.txt");
res.writeHead(200, {
"Content-Type": "application/x-javascript;charset=utf-8",
"Content-Encoding": "gzip",
});
readStream.pipe(gzip).pipe(res);
})
.listen(3000, () => {
console.log("server start");
});
压缩前
压缩后
八、crypto
crypto 模块提供了加密、解密、签名、验证等各种安全相关的功能
const crypto = require("crypto");
// 哈希计算
const hash = crypto.createHash("md5");
hash.update("123456");
console.log(hash.digest("hex"));
// 增强
const hashPlus = crypto.createHmac("md5", "secret-key");
hashPlus.update("123456");
console.log(hashPlus.digest("hex"));
// 对称加密
function encrypto(key, iv, data) {
let dep = crypto.createCipheriv("aes-128-cbc", key, iv);
return dep.update(data, "binary", "hex") + dep.final("hex");
}
function decrypto(key, iv, data) {
let cryptoed = Buffer.from(data, "hex").toString("binary");
let dep = crypto.createDecipheriv("aes-128-cbc", key, iv);
return dep.update(cryptoed, "binary", "utf8") + dep.final("utf8");
}
const encryptoed = encrypto("1122334455667788", "aabbccddeeffgghh", "stars");
console.log("加密", encryptoed);
console.log(
"解密",
decrypto("1122334455667788", "aabbccddeeffgghh", encryptoed)
);
转载自:https://juejin.cn/post/7233625509107810363