哈喽~今天来阐述几个node.js使用频率较高的模块(有没有人听啊不会显得我很弱吱吧),首先说明我是用于工业触摸屏和集控平台,对口的煲子们可以安心入座了,不对口的也要坐(威胁!)
如果要学习的话很简单哈,首先安装好node.js,关于搭建node.js的环境这里就不展开了,有超多大佬教学,本人感觉已经饱和了~
安装完成后新建一个文件夹,安装需要的模块,一般常用到的模块:modbus-serial、express、sqlite3、axios、cors、body-parser,安装指令:npm install xxx --save,好!讲到哪学到哪,有人疑惑了,这带个--save怎么事啊,不带行不行啊?
带 --save 选项:
使用 --save
选项时,npm 会自动将安装的模块及其版本号添加到项目的 package.json
文件的 dependencies
字段中。简单来说就是安装到了项目路径下,这些模块会在项目部署到生产环境时被安装。
不带 --save 选项:
如果不使用 --save
选项,npm 默认不会将安装的模块添加到 package.json
文件的 dependencies
字段中,会被安装到 node_modules
目录中,因此在其他环境中运行 npm install
时,这些模块不会被自动安装。
回到新建文件夹并安装模块部分,安装完后目录如下所示:
一共会出现三个文件,分别是文件夹 node_modules
、package.json
和
package-lock.json
,
结合图文总结:如果加了
--save
,项目路径发生改变或者在其他用户的环境下运行时,使用
npm install
,是可以一键安装的,而不加的话这些模块只在本地有效。
(❗注意:
在npm 5.0.0及更高版本中,npm install xxx --save
命令已经被简化为 npm install xxx
,因为 --save
已经成为默认行为,所以没必要加啦)
咱们继续说道说道,嫌麻烦的时候命令可以缩成一行哈,🌰如:
npm install modbus-serial express sqlite3 axios cors fs body-parser --save
一次性不要安上太多模块,以免超载(安装慢)
然后以我的习惯,会先用express搭一个http应用,好!讲到哪学到哪,这时候其实有中级学者发出疑问,这这好像还有个http模块,这不比express更像正主啊,为啥用express呢?
http 模块 :
http
模块用于创建HTTP服务器和客户端。它提供了底层的HTTP功能,适合用于简单的HTTP应用或者需要对底层HTTP协议进行精细控制的场景。 http
提供了对HTTP请求和响应的底层控制,它可以直接处理HTTP协议细节,缺点是需要手动处理请求路径、请求方法、请求头和响应头等等。
express 模块 :
express模块简化了HTTP服务器的创建和管理。它
提供了许多中间件、路由和模板引擎等功能以及社区文档查阅。
对比总结:express相对于http模块,内置路由功能,方便定义URL路径的处理逻辑;express支持中间件,方便添加各种功能;且支持多种模板引擎,方便生成动态HTML内容。
所以对于我们来说,还是express更加香啦,简单生成一个监听接口:
const express = require('express');
const app = express();
app.get('/here', (req, res) => {
res.send('Hello, World!');
});
app.listen(7000, () => {
console.log('Server running at http://127.0.0.1:7000/');
});
搜索 localhost:7000/here 就可以看到 Hello, World!了(小白接口教学请跑到隔壁教室!入门小白必看-前后端接口的调用和区别(后端篇))
这时候我们有个外部接口需要引入,然后存储一些数据,就再加入模块 axios 和 sqlite3:
const express = require('express');
const axios = require('axios');
const app = express();
var name = [];
app.get('/here', (req, res) => {
const response = await axios.get('http://192.168.1.xx:5000/name');
name = response.data;
res.status(200).json({ get all names : name });
});
app.listen(7000, () => {
console.log('Server running at http://127.0.0.1:7000/');
});
引入接口并用一个全局变量name获取数据,显示到/here上,这时需要新建数据库及建表,数据解析等操作,再引入sqlite3 和 body-parser:
const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const bodyParser = require('body-parser');
const axios = require('axios');
const app = express();
// 使用 body-parser 解析 JSON 请求体
app.use(bodyParser.json());
// 创建数据库连接
const db = new sqlite3.Database('db.robot', (err) => {
if (err) {
return console.error(err.message);
}
console.log('Connected to the SQlite database.');
});
var name = [];
// 初始化数据库和表
function initDB() {
db.serialize(() => {
db.run(`DROP TABLE IF EXISTS nameSave`);
// 创建表,如果不存在
db.run(`CREATE TABLE IF NOT EXISTS nameSave (
id INTEGER PRIMARY KEY,
name TEXT
)`);
});
}
// 初始化数据库和表
initDB();
// 获取数据并存储到数据库
app.get('/here', async (req, res) => {
try {
const response = await axios.get('http://192.168.1.xx:5000/name');
name = response.data;
// 将数据存储到数据库
name.forEach((nameItem) => {
db.run(`INSERT INTO nameSave (name) VALUES (?)`, [nameItem], function(err) {
if (err) {
return console.log(err.message);
}
console.log(`A row has been inserted with rowid ${this.lastID}`);
});
});
res.status(200).json({ "get all names": name });
} catch (error) {
console.error('Error fetching data:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
// 获取数据库中的所有名字
app.get('/names', (req, res) => {
db.all(`SELECT name FROM nameSave`, [], (err, rows) => {
if (err) {
return console.error(err.message);
}
res.status(200).json({ names: rows.map(row => row.name) });
});
});
app.listen(7000, () => {
console.log('Server running at http://127.0.0.1:7000/');
});
这时已经是一个相对完整的后端文件了,如果数据不从axios 引入的话,一般还有方法modbus,好!讲到哪学到哪,modbus-serial 模块也是必用的:
modbus-serial
作为工业自动化和控制系统不可缺少的通信协议,同时支持 Modbus RTU 和 Modbus TCP/IP ,支持主设备(Master)与从设备(Slave)之间的通信,共有9种功能码和4种读写方式,包括离散输入、线圈、保持寄存器和输入寄存器,详细可查询官网modbus-serial - npm
简单来说,我们要从串口读取数据,可以是格式如下:
const readData1 = function() {
tcpClient.setID(1);
let data1 = tcpClient.readHoldingRegisters(0, 60 , function(err, data) {
if (err) {
console.error('读取保持寄存器数据1时发生错误:', err);
} else {
data1 = data.data
console.log('the data of data1:', data1);
}
});
}
这里用的是Modbus TCP/IP,在readData1方法里, 设置设备ID为1,读取地址0开始,60个数据,如果长度不符、ID不对、ip地址不对,都会报错;如果正确读取,则会回复值给data1~
往回走,为什么说那个后端文件差不多呢,因为我们还有个 cors 没用到呢,很多前端页面的端口都是localhost:8000或者8080啥的对吧,那想和后端交互,两localhost相撞,一山不容二虎呀,必出现跨域问题,不过前后端都可以解决,我们这回先通过cors 模块:
const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const bodyParser = require('body-parser');
const axios = require('axios');
const cors = require('cors');
const app = express();
app.use(
cors({
origin: ["http://localhost:8000", "http://192.168.1.*:8000"],
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
})
);
app.use(...)
: 这就是Express.js的一个方法,用于挂载中间件;
cors(...)
: 这是一个用于处理CORS的中间件函数。它接受一个配置对象作为参数,用于定义哪些请求是被允许的;
origin:
这里设置了允许跨域请求的来源。origin
可以是一个字符串、一个数组或者一个函数。在这个例子中,我们允许来自http://localhost:8000
和所有匹配http://192.168.1.*:8000
模式的来源的请求。*
在这里是一个通配符,表示允许来自192.168.1
子网中所有IP地址的请求,只要它们的端口号是8000;
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']
: 这个配置定义了允许的HTTP方法;
allowedHeaders: ['Content-Type', 'Authorization']
: 这个配置定义了哪些HTTP头部可以被浏览器发送。
综述总结:加了cors,就可以完美解决前后端跨域问题,动态根据ip地址增减哈~
还有很多常用模块,🌰如:fs、path等等,还想听的堡子们指出来再出一期,指哪打哪~