关于node.js:锁定项目-Node-版本和包管理器

通过文档和沟通束缚,远不如用工具(代码)束缚。开发环境Node.jsPackage Manager (npm、yarn、pnpm)痛点问题成员机器 Node.js 版本不对立: 守旧派用 12.x、激进用 14.x、激进用 17.x。我的项目是否失常跑起来全凭天意,在没有 CICD 流水线加持本地 npm run build 的场景下线上危险可想而知。 有人习惯用 npm、有人习惯用 yarn, 代码库外面常常会存在 package-lock.json、yarn.lock 文件同时存在的状况。更痛的点还是各种奇奇怪怪问题排查起来没有脉络。 咱们要做的就是将问题掐死在源头:锁定 Node.js 版本和包管理器 锁定我的项目 Node 版本通过在 package.json 中指定 engines 字段,可限定我的项目应用的 node 版本。上面配置仅容许用户应用 14 或者 16的版本。更多的配置能够参考 package.json | npm Docs 、semver // package.json "engines": { "node": "14.x || 16.x" },配置之后你会发现,该字段只对 yarn 失效。那如何对 npm 也失效呢?在我的项目根目录下的 .npmrc 文件中减少如下配置 // .npmrcengine-strict = true以上配置实现后,npm install 试试吧,谬误的 Node.js 将间接退出 锁定包管理器利用 only-allow 工具包、npm scripts 疾速实现锁定。 ...

May 30, 2022 · 1 min · jiezi

关于node.js:在puppeteer中使用nodejs创建子进程并使用WebSocket和Ipc实现进程间通信从而实现数据的快速爬取

笔者近几月某公司WiFi测试平台我的项目中,理解到他们测试WiFi始终是人工手动测试,因而在老师提议下,决定采纳puppeteer去实现页面数据的爬取和更改的自动化,在施行过程中,发现--路由治理页面--登陆后只有cookie加密,并且页面的数据和操作通过向同一接口传递不同参数实现,因而能够通过promise-request办法疾速的实现上述性能。本文次要记录、总结: node.js子过程的创立:node.js:child_process(官网文档)fork和spawn的区别与分割Ipc实现过程间通信WebSocket实现过程间通信1. node.js子过程的创立node创立子过程的办法能够参考上述官网文档,外面有具体的配置和阐明。在本文中,笔者着重介绍笔者应用到的child_process.spawn()办法和child_process.fork()办法。Master过程代码: const child_process = require('child_process');//引入child_process模块const {recLog} = require("./utils/log");//因为执行父过程,子过程无奈在控制台打印信息,因而封装了log4js办法。const gChildProcessNumber = 3;//创立子过程数量-全局creatProcess();async function creatProcess() { for (let i = 0; i < gChildProcessNumber; i += 1) { const workerProcess = child_process.spawn('node', ['./Request_Test/ChildProcess.js']); }}Child过程代码: const {recLog} = require("./utils/log");recLog(`子过程创立胜利,执行ChildProcess.js文件,过程pid为:${process.pid}`)执行后果:留神:这里应用child_process.spawn()办法,因为笔者子过程运行的文件为js文件,因而间接用node运行,如果运行的是其余文件,比方笔者之前运行的×××.e2e.js文件时,笔者运行指令为npm test ×××.e2e.js,就须要写成如下: const workerProcess = child_process.spawn('npm.cmd', ['test', './Request_Test/request.e2e.js'], { });因为在Windows上,当咱们执行npm 时,咱们理论执行的是npm. cnd批处理,所以肯定要显示的执行npm.cmd否则会呈现Error: spawn npm ENOENT的谬误。(未完)

May 28, 2022 · 1 min · jiezi

关于node.js:vs-code调试nodejs代码

文章不易,请关注公众号 毛毛虫的小小蜡笔,多多反对,谢谢 前言几年前开始调试node.js,比方想深刻查看node.js相干我的项目的代码,很多人根本是通过chrome的node-inspect来调试的。 但也有些人不喜爱打断点来调试,而是间接通过console.log来定位查看问题。 不论是哪种形式,各有优缺点。 vs code调试node.js当初曾经有了一种新的调试形式,就是在IDE中进行调试。 比方在vs code的IDE,设置好auto attach后,就能够在启动node.js后,就进入调试模式。 详情 请查看:毛毛虫的小小蜡笔

May 27, 2022 · 1 min · jiezi

关于node.js:NodeCorepack

CorepackCorepack是一个实验性工具,在 Node.js v16.13 版本中引入,它能够指定我的项目应用的包管理器以及版本, 简略来说,Corepack 会成为 Node.js 官网的内置 CLI,用来治理『包管理工具(yarn、pnpm)』,用户无需手动装置,即『包管理器的管理器』。 用法因为corepack 是一个实验性工具,所以默认是没有启动的,须要显式启用,须要运行指令 corepack enable 进行启动;在我的项目package.json 文件中新增属性 "packageManager",比方 "packageManager": "yarn@1.22.15"代表以后我的项目只容许应用yarn 包管理器并指定1.22.15版本 // 以后利用激活corepack enable// 定义包管理器packageManager": "yarn@1.22.15"// 申明的包管理器,会主动下载对应的 yarn,而后执行yarn install// 用非申明的包管理器,会主动拦挡报错pnpm installUsage Error: This project is configured to use yarn因为在试验阶段,目前还有些问题待解决: 目前仅反对 pnpm 和 yarn,cnpm 也是不反对的兼容性还有些问题,npm 还无奈拦挡也就是说 即使配置了 packageManager 应用 yarn,然而仍然能够调用全局 npm 装置

May 25, 2022 · 1 min · jiezi

关于node.js:用czrelax-轻松配置commit友好的仓库

结尾一张图 之前《让你的commit更有价值》中配置 commitizen 须要好几步,例如首先 commitizen 须要进行初始化并且抉择 commitizen adapter,而后须要装置 commitlint ,最初可能还须要 husky 配置 git hooks。 当初,只须要两步,就能够实现下面的工作,让所有变得轻松起来。 1. 在工作目录装置 cz-relaxnpm install cz-relax --save-dev2. 初始化npx cz-relax init如果想应用中文提醒: npx cz-relax init --language zh实现下面两步,你就能够失常的应用 git commit了,此时 commitizen 就失效了。 此外,cz-relax 默认应用的 adapter 是 cz-git,属于反对国产了。 反馈倡议仓库地址:https://github.com/qiqihaoben...ISSUES: https://github.com/qiqihaoben...

May 16, 2022 · 1 min · jiezi

关于node.js:Nodejs-RESTful-API

Node.js RESTful API 什么是 REST?REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构格调。 表述性状态转移是一组架构约束条件和准则。满足这些约束条件和准则的应用程序或设计就是RESTful。须要留神的是,REST是设计格调而不是规范。REST通常基于应用HTTP,URI,和XML(规范通用标记语言下的一个子集)以及HTML(规范通用标记语言下的一个利用)这些现有的宽泛风行的协定和规范。REST 通常应用 JSON 数据格式。 HTTP 办法以下为 REST 根本架构的四个办法: GET - 用于获取数据。PUT - 用于更新或增加数据。DELETE - 用于删除数据。POST - 用于增加数据。RESTful Web ServicesWeb service是一个平台独立的,低耦合的,自蕴含的、基于可编程的web的应用程序,可应用凋谢的XML(规范通用标记语言下的一个子集)规范来形容、公布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。基于 REST 架构的 Web Services 即是 RESTful。 因为轻量级以及通过 HTTP 间接传输数据的个性,Web 服务的 RESTful 办法曾经成为最常见的代替办法。能够应用各种语言(比方 Java 程序、Perl、Ruby、Python、PHP 和 Javascript[包含 Ajax])实现客户端。 RESTful Web 服务通常能够通过主动客户端或代表用户的应用程序拜访。然而,这种服务的简便性让用户可能与之间接交互,应用它们的 Web 浏览器构建一个 GET URL 并读取返回的内容。 更多介绍,能够查看:RESTful 架构详解 创立 RESTful首先,创立一个 json 数据资源文件 users.json,内容如下: { "user1" : { "name" : "mahesh", "password" : "password1", "profession" : "teacher", "id": 1 }, "user2" : { "name" : "suresh", "password" : "password2", "profession" : "librarian", "id": 2 }, "user3" : { "name" : "ramesh", "password" : "password3", "profession" : "clerk", "id": 3 }}

May 14, 2022 · 1 min · jiezi

关于node.js:nextjs-typescript-配置paths-alias

在tsconfig.json下, 能够配置path的alias 须要额定几个配置 build时减少tsc-alias npm i tsc-alias --save-dev 运行时减少tsconfig-paths npm i tsconfig-paths --save-dev

May 13, 2022 · 1 min · jiezi

关于node.js:安装node全局配置

1、安装包下载https://nodejs.org/en/download/ 2、如果不是全局装置,查看node,提醒没有该命令。须要配置全局(1)首先在cmd命令行窗口 执行指令npm config set prefix “C:\Program Files\nodejs\node_global” npm config set cache “C:\Program Files\nodejs\node_cache”(2)接着,在环境变量窗口,将【零碎变量】下新建【NODE_PATH】,输出 【D:\Develop\nodejs\node_global\node_modules】,将【用户变量】下的【Path】编辑 【C:\Users\Administrator\AppData\Roaming\npm】批改为【C:\Program Files\nodejs\node_global\】我本人的是: 【C:\Program Files\nodejs\】批改为【C:\Program Files\nodejs\node_global\】————————————————版权申明:本文为CSDN博主「广积粮缓称王」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。原文链接:https://blog.csdn.net/zhouzuo...

May 12, 2022 · 1 min · jiezi

关于node.js:node-异常数据响应排查pm2-Cluster-Mode异步

昨天收到一个铁子的反馈 node 外面写的一个 js 文件外面的办法,这个 js 文件外面有申明一个 var 全局变量(global),而后下面说到的办法就是先判断全局变量是否有值,要是就值就间接返回,要是没有值就通过接口去获取值; 而后在页面上特定的一个操作之后,会把这个全局变量的值清空为null,而后就走下面的获取接口的值本地失常,服务器上谬误他们给出的信息必定是不够的,我就顺嘴问了几个信息 是不是报错?因为报错会导致 Node 利用重启,继而导致状态生效。 没报错是否提供复现代码?这里个别取决于我的项目的体量,或者目前问题定位进度 无奈提供。本地失常,服务器上谬误执行环境是什么?commonjs?ESM?Ts?这里想看看是不是有什么骚操作,比如说 serverless 之类的无奈保留状态。 Node而后还问了本地和服务器通过什么启动的服务?这里我想确认一下是不是 Cluster ,因为 Cluster 状态是不共享,须要非凡计划。 node其实到这里我就晓得,这个人不是业余做 Node 的,后面的信息有可能也有毒。 这个时候忽然给我发来了日志截图,这间接破案了。Cluster 模式数据共享问题,本地 node 起的服务所以不存在这个问题,服务器应该是 pm2 start index.js -i 4 之类的。 0| www xxxxx1| www xxxxx3| www xxxxx0| www xxxxx接下来就是最小复现 demo 排查问题,修复计划了。 复现 Cluster 数据共享问题其实在他让我看到是 Cluster 的时候就曾经定位到问题了,非常明显的数据共享问题。 上面来看咱们的复现例子,能够发现单个实例输入是正确的,正是因为申请落到不同的机器(实例)导致不同的响应。 if (!global.a) { global.a = 1}console.log(global.a, Date.now())function randomTask() { console.log(++global.a, Date.now()) if (global.a < 5) { setTimeout(randomTask, Math.random() * 1000) }}randomTask(); ...

May 9, 2022 · 2 min · jiezi

关于node.js:模拟可读流可写流实现

可读流模仿实现 const fs = require("fs");const EventEmitter = require("events");class MyFileReadStream extends EventEmitter { constructor(path, options = {}) { super(); this.path = path; this.flag = options.flags || "r"; this.mode = options.mode || 438; this.autoClose = options.autoClose || true; this.start = options.start || 0; this.end = options.end; this.highWaterMark = options.highWaterMark || 64 * 1024; this.readOffset = 0; this.open(); this.on("newListener", (type) => { // 判断监听类型 console.log(type); if (type === "data") { this.read(); } }); } open() { // 原生open办法关上指定地位文件 fs.open(this.path, this.flags, this.mode, (err, fd) => { if (err) { this.emit("error", err); } else { this.fd = fd; this.emit("open", fd); // 发送文件标识符 } }); } read() { // 这里无奈间接获取fd,这里监听一下open工夫,管制执行程序 if (typeof this.fd !== "number") { return this.once("open", this.read); } let buf = Buffer.alloc(this.highWaterMark); let howMuchToRead; // 用户设置了end值 howMuchToRead = this.end ? Math.min(this.end - this.readOffset + 1, this.highWaterMark) : this.highWaterMark; fs.read( this.fd, buf, 0, howMuchToRead, this.readOffset, (err, readBytes) => { if (readBytes) { this.readOffset += readBytes; this.emit("data", buf.slice(0, readBytes)); // 返回数据 this.read(); // 持续读 } else { this.emit("end"); this.close(); } } ); } close() { fs.close(this.fd, () => { this.emit("close"); }); } // pipe简化了操作 pipe(ws) { this.on("data", (data) => { let flag = ws.write(data); if (!flag) { this.pause(); } }); ws.on("drain", () => { this.resume(); }); }}let rs = new MyFileReadStream("test.txt", { end: 7, highWaterMark: 3,});//事件触发测试// rs.on("open", (fd) => {// console.log("open", fd);// });// rs.on("error", (err) => {// console.log(err);// });rs.on("data", (chunk) => { console.log(chunk);});// rs.on("end", () => {// console.log("end");// });rs.on("close", () => { console.log("close");});可写流模仿实现 ...

May 4, 2022 · 3 min · jiezi

关于node.js:文件可读流可写流drain事件背压机制

可读流案例 // 文件可读流创立和生产const fs = require("fs");let rs = fs.createReadStream("test.txt", { flags: "r", encoding: null, fd: null, mode: 438, autoClose: true, start: 0, // end:3, highWaterMark: 4,});// rs.on('data',(chunk)=>{// console.log(chunk.toString())// rs.pause() // 暂停// setTimeout(() => {// rs.resume() // 切回流动状态// }, 1000); // 1秒后持续,直到完结// })// rs.on("readable", () => {// // let data = rs.read();// // console.log(data);// let data;// // while ((data = rs.read()) !== null) {// // console.log(data.toString());// // }// while ((data = rs.read(2)) !== null) { // 每次读两字节,缓冲区读完之后取highWaterMark字节长度到缓冲区// console.log(data.toString());// console.log(rs._readableState.length);// }// });rs.on("open", (fd) => { console.log(fd, "file open");});rs.on("close", (fd) => { console.log("默认不会被执行,数据被读取完(生产)后才会被执行");});rs.on("data", (chunk) => { console.log(chunk);});rs.on("end", () => { console.log('数据被清空过之后会被执行');});rs.on("err", (err) => { console.log('出错时会被执行');});可写流案例 ...

May 4, 2022 · 2 min · jiezi

关于node.js:node网络通信

网络通信一、网络通信1.网络通信基本原理通信必要条件: 主机之间须要有传输介质(数据信号的传输)主机上必须有网卡设施(数据信号的调制与解调制)主机之间须要协商网络速率图示: 2.网络通信形式交换机通信路由器通信图示:(利用Mac地址,定位主机)毛病: 交换机的接口数量有下限局域网存在大量主机会造成播送风暴(任意一条音讯都须要其它机器接管,再确认受否无效)路由器应用(连贯局域网)图示: 3.网络层次模型OSI七层模型:数据的封装与解封装(TCP/IP五层协定模式):参考:https://blog.csdn.net/weixin_... 4.tcp协定tcp报文构造图解:常见管制字段:三次握手图解:四次挥手图解: 为什么挥手中,两头两次不能合并呢? 一个服务端会服务于多个客户端,服务端接管到音讯后,不肯定能即便将后果及时传回TCP协定总结: TCP处于传输层,基于端口,面向连贯主机之间要想通信须要先建设双向数据通道TCP的握手与挥手实质上都是四次二、创立TCP通信Net模块实现了底层通信接口通信过程: 创立服务端:接管和回写客户端数据创立客户端:发送和接管服务端数据数据传输:内置服务事件和办法读写数据外围内置通信事件: listening事件:调用server.listen办法之后触发connection事件:新的连贯建设时触发close事件:当server敞开时触发error事件:当谬误呈现的时候触发通信事件&办法: data事件:当接管到数据的时候触发该事件write办法:在socket上发送数据,默认是UTF8编码end操作:当socket的一端发送FIN包时触发,完结可读端1.net模块应用node中tcp连贯的创立与通信:server: const net = require('net');// 创立服务端实例const server = net.createServer();const PORT = 1234;const HOST = 'localhost';// 监听该端口server.listen(PORT, HOST);server.on('listening',()=>{ console.log(`服务端曾经开启在 ${HOST}:${PORT}`);});// 就收音讯,回写音讯 socket 双工流server.on('connection',(socket)=>{ console.log('有客户端连贯'); socket.on('data',(chunk)=>{ const msg = chunk.toString(); console.log('client:'+msg); // 回写音讯 socket.write(Buffer.from('hello client')); })});server.on('close',()=>{ console.log('服务端曾经敞开');})server.on('error',(err)=>{ console.log('服务端产生谬误',err);})client: const net = require('net');const client = net.createConnection({ port: 1234, host: '127.0.0.1'})client.on('connect', () => { client.write('hello server');})client.on('data',(chunk)=>{ console.log('server:'+chunk.toString());});client.on('err',()=>{ console.log('客户端产生谬误');});client.on('close',()=>{ console.log('客户端曾经敞开');})2.TCP粘包问题问题展现:client代码: client.on('connect', () => { client.write('hello server'); client.write('hello server'); client.write('hello server'); client.write('hello server');})server代码: ...

May 3, 2022 · 3 min · jiezi

关于node.js:node常用内置模块Stream

node罕用内置模块(Stream)一、Stream理解node.js中的流就是解决流式数据的形象接口,文件操作系统和网络模块实现了流接口不应用流的常见问题: 同步读取资源文件,用户与要期待数据读取实现资源文件最终一次性加载至内存,开销较大应用流的图解(数据的分段传输):配合管道对需要的加工:流解决数据的劣势: 工夫效率:流的分段解决能够同时操作多个数据chunk空间效率:同一时间流毋庸占据大内存空间使用方便:流配合治理,扩大程序变得简略node.js中流的分类: Readalbe:可读流,可能是实现数据的读取Writealbe:可写流,可能实现数据的写操作Duplex:双工流,既可读又可写Transform:转换流,可读可写,还是实现数据转换nodejs流特点: Stream模块实现了四个具体的形象所有流都继承自EventEmitter二、根本API1.可读流专门生产供程序生产数据的流自定义可读流: 继承stream里的Readable重写_read办法调用push产出数据可读流基本原理:生产数据: readable事件:当流中存在可读取的数据是触发data事件:当流中数据块传给消费者后触发自定义可读流代码实现: const { Readable } = require('stream');// 模仿底层数据let source = ['lg', 'zce', 'syy'];class MyReadable extends Readable { constructor(source) { super(); this.source = source; } _read() { let data = this.source.shift() || null; // 如果没有数据,则返回 null this.push(data); // 将数据推入到流中 }}let mr = new MyReadable(source);// reaadable 默认是暂停模式 // mr.on('readable', () => {// let data = null;// while(data = mr.read(2)){// console.log(data.toString());// }// })// 有可能都不放入缓存中,间接输入mr.on('data', (chunk) => { console.log(chunk.toString());})2.可写流用于生产数据的流自定义可写流: ...

May 3, 2022 · 6 min · jiezi

关于node.js:Nodejs文件目录操作实例

文件关上和敞开fs.open(path.resolve("data.txt"), "r", (err, fd) => { console.log(fd); // 3});fs.open("data.txt", "r", (err, fd) => { console.log(fd); fs.close(fd, (err) => { console.log('close successful'); });});大文件读写操作波及open和write两个办法 // read 读操作就是将数据从磁盘文件写入到buffer中// read(fd: number, --定位以后被关上的文件// buffer: Buffer, --用于标识以后缓冲区// offset: number, --从buffer哪个地位开始写操作// length: number, --以后次写入的字节长度// position: fs.ReadPosition, --从磁盘文件中哪一个字节开始读取// callback: (err: NodeJS.ErrnoException, bytesRead: number, buffer: Buffer) => void): voidlet buf = Buffer.alloc(10);fs.open("data.txt", "r", (err, readfd) => { console.log(readfd); fs.read(readfd, buf, 1, 3, 2, (err, readBytes, data) => { console.log(readBytes); console.log(data); console.log(data.toString()); });});// write(fd: number,--定位以后被关上的文件// buffer: Buffer, --用于标识以后缓冲区// offset: number, --从buffer哪个地位开始读取数据// length: number, --以后次写的字节长度 // position: number, --从哪个字节开始写操作// callback: (err: NodeJS.ErrnoException, written: number, buffer: Buffer) => void): voidlet buf = Buffer.from('1234567890')fs.open('a.txt','w',(err,writefd)=>{ fs.write(writefd,buf,1,3,0,(err,written,buffer)=>{ console.log(written) // 3 console.log(buffer) // <Buffer 31 32 33 34 35 36 37 38 39 30> console.log(buffer.toString()) // 1234567890 fs.close(writefd) })})文件拷贝自定义实现/** * 1关上a文件,利用read将数据保留到buffer暂存起来 -- a文件内容为1234567890 * 2,关上b文件,利用write将buffer中数据写入到b文件 */let buf = Buffer.alloc(10);// 关上指定文件fs.open("a.txt", "r", (err, readfd) => { // 关上b文件,用于执行数据写入操作 fs.open("b.txt", "w", (err, writefd) => { // 从关上的文件读取数据 fs.read(readfd, buf, 0, 10, 0, (err, readBytes) => { // buffer写入到b.txt中 fs.write(writefd, buf, 0, 10, 0, (err, wirtten) => { console.log("write successful"); }); }); });});针对大文件边读边写,利用buffer缓冲区实现操作 ...

May 1, 2022 · 3 min · jiezi

关于node.js:Nodejs基础使用PathBufferfs

Pathconst path = require('path')console.log(__filename)// 获取门路根底名称,最初一部分/** * 返回的就是接管门路当中的最初一部分 * 第二个参数示意扩展名,如果没有设置就返回残缺文件名带后缀 * 第二个参数作为后缀时,如果没有在以后门路中被匹配到,那么就会疏忽 * 解决目录门路的时候如果结尾处有门路分隔符,则也会被疏忽掉 */console.log(path.basename(__filename))console.log(path.basename(__filename,'.js')) // 第二个可选参数,匹配后缀,有就显示文件名称,没有就反正残缺文件名console.log(path.basename(__filename,'.css'))console.log(path.basename('/a/b/c')) // 返回path门路最初一部分// 获取门路目录名(门路)/** * 返回门路中最初一个局部的上一层目录所在门路 */console.log(path.dirname(__filename))console.log(path.dirname('/a/b/c')) // /a/b console.log(path.dirname('/a/b/c/')) // /a/b// 获取门路扩展名/** * 返回path门路中相应文件的后缀名 * 如果path门路当中存在多个点,它匹配的是最初一个点到结尾的内容 * */console.log(path.extname(__filename)) // .jsconsole.log(path.extname('/a/b')) // 空console.log(path.extname('/a/b/index.html.js.css')) // .cssconsole.log(path.extname('/a/b/index.html.js.')) // .// 解析门路/** * 接管一个门路,返回一个对象,蕴含不同的信息 * root dir base ext name(最初一部分名称) */const obj = path.parse('a/b/c/index.html')// {// root: '',// dir: 'a/b/c',// base: 'index.html',// ext: '.html',// name: 'index'// }const obj1 = path.parse('a/b/c/') // { root: '', dir: 'a/b', base: 'c', ext: '', name: 'c' }const obj2 = path.parse('a/b/c') // { root: '', dir: 'a/b', base: 'c', ext: '', name: 'c' }const obj3 = path.parse('./a/b/c') // { root: '', dir: './a/b', base: 'c', ext: '', name: 'c' }// 序列化门路const obj4 = path.parse('./a/b/c') console.log(path.format(obj4)) // ./a/b\c// 判断以后门路是否为绝对路径console.log(path.isAbsolute('foo')) // falseconsole.log(path.isAbsolute('/foo')) // trueconsole.log(path.isAbsolute('///foo')) // trueconsole.log(path.isAbsolute('')) // falseconsole.log(path.isAbsolute('.')) // falseconsole.log(path.isAbsolute('../bar')) // false// 拼接门路console.log(path.join('a/b','c','index.html')) // a\b\c\index.htmlconsole.log(path.join('/a/b','c','index.html')) // \a\b\c\index.htmlconsole.log(path.join('a/b','c','../','index.html')) // a\b\index.htmlconsole.log(path.join('a/b','c','./','index.html')) // a\b\c\index.htmlconsole.log(path.join('a/b','c','','index.html')) // a\b\c\index.htmlconsole.log(path.join('')) // . 当前工作目录// 规范化门路console.log(path.normalize('a/b/c/d')) // a\b\c\dconsole.log(path.normalize('a///b/c../d')) // a\b\c..\dconsole.log(path.normalize('a//\\b/c\\/d')) // a\b\c\dconsole.log(path.normalize('a//\b/c\\/d')) // a\c\d 反斜杠后字母具备非凡意义console.log(path.normalize('')) // .// 绝对路径console.log(path.resolve()) // 打印当前目录console.log(path.resolve('index.html')) // 打印当前目录/index.html 最罕用写法console.log(path.resolve('a','b')) // 当前目录\a\b/** * resolve([from],to) 把to局部拼接为绝对路径,如果拼接完并不是一个绝对路径, * 那就把当前工作目录加上,让他成为一个绝对路径。from */console.log(path.resolve('/a','b')) // D:\a\b 这里 '/a' 'b'成为了toconsole.log(path.resolve('a','/b')) // D:\b 这里a被疏忽, '/b'成为了toconsole.log(path.resolve('/a','/b')) // D:\b 这里 '/a'被疏忽 '/b'成为了toBufferBuffer让Js能够操作二进制全局变量,毋庸require的一个全局变量实现nodejs平台下的二进制数据操作不占据V8堆内存大小的内存空间内存的应用由Node管制,由v8的GC回收个别配合Stream流应用个,充当数据缓冲区 ...

April 30, 2022 · 4 min · jiezi

关于node.js:Nodejs应用markdown文件转html

实现思路: 01 读取 md 和 css 内容02 将上述读取进去的内容替换占位符,生成一个最终须要展的 Html 字符串03 将上述的 Html 字符写入到指定的 Html 文件中04 监听 md 文档内容的变经,而后更新 html 内容05 应用 browser-sync 来实时显示 Html 内容须要用到两个依赖包 { "name": "04-md", "version": "1.0.0", "main": "index.js", "license": "MIT", "devDependencies": { "browser-sync": "^2.27.9", "marked": "^4.0.14" }}实现代码 const fs = require("fs");const path = require("path");const { marked } = require("marked");const browserSync = require("browser-sync");let mdPath = path.join(__dirname, process.argv[2]);let cssPath = path.resolve("github.css"); // 初始化款式let htmlPath = mdPath.replace(path.extname(mdPath), ".html");console.log(mdPath, cssPath, htmlPath);// 监听fs.watchFile(mdPath, (cur, pre) => { if (cur.mtime !== pre.mtime) { fs.readFile(mdPath, "utf-8", (err, data) => { // 将 md-->html let htmlStr = marked(data); fs.readFile(cssPath, "utf-8", (err, data) => { let retHtml = temp .replace("{{content}}", htmlStr) .replace("{{style}}", data); // 将上述内容写入到指定的html文件中,用于在浏览器中展现 fs.writeFile(htmlPath, retHtml, (err) => { console.log("html create successful"); }); }); }); }});browserSync.init({ browser: "", server: __dirname, watch: true, index: path.basename(htmlPath),});// html模板const temp = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .markdown-body { box-sizing: border-box; min-width: 200px; max-width: 1000px; margin: 0 auto; padding: 45px; } @media (max-width: 750px) { .markdown-body { padding: 15px; } } {{style}} </style> </head> <body> <div class="markdown-body"> {{content}} </div> </body> </html>`;

April 30, 2022 · 1 min · jiezi

关于node.js:node常用内置模块events

node罕用内置模块(events)一、事件模块events通过EventEmitter类实现事件对立治理罕用API: on:增加事件监听emit:触发事件once:增加只触发一次的事件监听off:移除特定的监听代码展现: const EventEmitter = require('events');const ev = new EventEmitter();ev.once('start', (...args) => { // 只执行一次 console.log('start once', args);});ev.on('start', function() { console.log('tart on'); console.log('this',this);})ev.emit('start','message data');// offlet startcb = ()=>{ console.log('jiang')}ev.on('startcb', startcb);ev.off('startcb',startcb);ev.emit('startcb'); // 不会触发const fs = require('fs');// 许多内置模块都继承了EventEmitter类,可间接应用该类的办法const crt = fs.createReadStream();crt.on('data')二、公布订阅模式定义对象间一对多的依赖关系模式图解:因素: 缓存队列,寄存订阅者信息具备减少、曹处订阅的能力状态扭转时告诉所有订阅者执行监听模仿实现: class PubSub { constructor() { this._events = {} } subscribe(event, callback) { if (this._events[event]) { this._events[event].push(callback); } else { this._events[event] = [callback]; } } publish(event, ...args) { const items = this._events[event]; if (items && items.length) { items.forEach(callback => { callback.call(this, ...args); }) } }}let ps = new PubSub();ps.subscribe('event1',(...args)=>{ console.log('event1 run end',args);})ps.publish('event1','event1 data')EventEmitter模仿实现: ...

April 30, 2022 · 2 min · jiezi

关于node.js:Nodejs-的相对于其他语言的优势分析

Node.js 是一门在浏览器外运⾏ JavaScript 的语言,运行时引擎是V8(Google Chrome 的内核)。也就是说能够用同一个技术栈去写web前后端的实现代码,这个个性应该是在所有语言中应该是举世无双的。 Node 是天生非阻塞式的异步io语言主线程是单线程,主线程中的操作是同步阻塞的。但它把所有须要异步的操作扔给了IO线程池,主线程通过肯定的事件轮询机制与IO线程池交互失去异步数据。,这便是node单线程和事件驱动的精华之处了。---具体参见NodeJs 的 Event loop 事件循环机制详解 这个个性使得nodejs应用在高并发互联网、物联网、数据中台更具劣势。 你可能会问为何具备高并发的劣势?要从以下几点说1.数据类型是弱类型的劣势,弱类型在传值的时候,是不会去强制转化类型的,弱类型简直都是json操作。因而在数据传递转换方面是缩小了开销的。例如其余强类型语言,在c层须要转换成承受的vo模型,s层还须要转化成do模型,dao层还须要转化成实体模型。这些在运行时都会在内存中耗费性能。尤其是在数据在乘以万倍以上的状况下。 2.nodejs的异步IO实现的形式,是无锁线程模型,用一个过程实现多个线程的模型,WorkerThread间及主线程间不能应用同一块内存。 这种模型在单节点有比拟高吞吐量与低提早个性,比用Cassandra的实现模型速度要快。 劣势方面,以下几点1.正是因为是弱类型,所以对于开发的程序员技术上的要求会更多,须要提供清晰的api文档,和残缺单元测试和覆盖率。2.Cpu密集计算的业务场景,如果业务须要做大量的高复杂度计算,那么选多线程模型语言可能更具备劣势,nodejs须要用多Worker的形式来进步cpu的利用率。 总体言之: 对于其余语言中规中矩,nodejs下限会更高,同时上限也很低。开发人员如果对业务清晰,多利用其异步个性,在避开nodejs的弱点,那么就能输入更高效的程序。

April 29, 2022 · 1 min · jiezi

关于node.js:nodejs模块化

nodejs模块化一、模块化倒退历程传统开发常见问题: 命名抵触和净化代码冗余,有效申请多文件的依赖关系简单模块:小而精,利于保护的代码片段常见模块化标准 CommonJS标准 node.js(同步加载)AMD标准 require.js(异步加载,依赖前置)CMD标准 sea.js(异步加载,就近依赖)ES6模块化 原生(编译时,异步加载)当下罕用的标准是Commonjs与ESM,参考文档:https://www.cnblogs.com/echoy... 二、CommonJS标准(语言层面上的标准)三个根底实现: 模块定义 模块标识 模块援用node.js与CommonJS: 任意一个文件就是一个模块,具备独立的作用域应用require导入其它模块将模块ID传入require实现目标模块定位CommonJS在nodejs中的实现:module属性 任意一个js文件就是一个模块,可间接应用module属性id:返回模块标识符,个别是一个绝对路径filename:返回文件模块的绝对路径loaded:返回布尔值,示意模块是否实现加载parent:返回对象,寄存了调用以后模块的模块children:返回一个数组,寄存以后模块调用的其它模块exports:返回以后模块须要裸露的内容paths:返回数组,寄存不同目录下的node_modules的地位module.exports与exports的区别 两者指向同一个内存地址,当exports从新赋值之后,exports就相当于一个局部变量了 require属性 基本功能是读入并执行一个模块文件,返回这个模块文件的moudule.exports对象resolve:返回模块文件绝对路径extensions:依据不同后缀名执行解析操作main:返回主模块对象nodejs中CommonJS标准的代码实现: //主模块// 一、模块的导入与导出const m = require('./m');console.log(m)// 二、module// console.log('no_module',module);// 三、exports// console.log(m)// 四、同步加载// 判断以后模块是否为主模块console.log(require.main === module) // require.main 指向本人//外置模块:// 一、模块的导入与导出const age = 18;const addFn = (x, y) => { return x + y;}// module.exports = {// age,// addFn// }// 二、module// console.log('no_module',module);// 三、exportsexports.name = 'jiang';// 四、同步加载let name = 'lg';// let iIime = Date.now();// while(Date.now() - iIime < 4000) {} // 同步加载,阻塞以后线程exports.nickName = name;console.log('m.js执行了')// 判断以后模块是否为主模块console.log(require.main === module) // require.main parent三、模块加载缓存优先准则模块分类: ...

April 29, 2022 · 2 min · jiezi

关于node.js:Nodejs-18-新特性解读

如何疾速体验举荐用fnm ,nvs,nvm等 Node.js 版本管理器。 $ fnm install 18Installing Node v18.0.0 (arm64) $ fnm use 18Using Node v18.0.0 $ node -vv18.0.0复制代码须要留神的是,该版本不是 LTS 版本,请勿在生产环境应用,须要等到 2022-10-25 才会成为 LTS 版本。 Looking to the futureThe project is also continuing its ‘Next 10’ effort. The goal of this effort is to reflect on what led to success in the first 10 years of Node.js and set the direction for success in the next 10. Node.js 官网启动了 next-10next-10 工作,并探讨出了将来重要的几件事将来重要的几件事将来重要的几件事: ...

April 28, 2022 · 2 min · jiezi

关于node.js:node常用内置模块fs模块

node罕用内置模块(fs模块)划分:文件操作的三个基本概念:权限位、标识符、操作符 1.基本操作类2.罕用API个别分为异步操作与同步操作,这里应用异步操作试验(一次性的文件操作,没有应用buffer),Node.js中有谬误优先的概念,当操作可能会呈现谬误时,回调函数的第一个参数常是谬误对象 const fs = require('fs');const path = require('path');// readFilefs.readFile(path.resolve('msg.txt'), 'utf-8', (error, data) => { if (!error) console.log(data);});// writeFile (overwrite),门路不存在时,会创立门路,操作配置对象,可省略fs.writeFile(path.resolve('msg.txt'), 'Hello Node.js', { mode: 0o666, // 权限 flag: 'a+', // 追加 encoding: 'utf-8' // 编码}, (error) => { if (!error) console.log('write success');})// apendFilefs.appendFile(path.resolve('msg.txt'), '\nHello Node.js', {}, (err) => { if (!err) console.log('append success');});// copyFilefs.copyFile(path.resolve('msg.txt'), path.resolve('msg2.txt'), (err) => { if (!err) console.log('copy success');});// watchFilefs.watchFile(path.resolve('msg.txt'), { interval: 1000},(curr, prev) => { console.log(curr.mtime); console.log(`${curr.size} ${prev.size}`);})fs.appendFile(path.resolve('msg.txt'), '\nHello Node.js', {}, (err) => { if (!err) console.log('append success22'); setTimeout(() => { fs.unwatchFile(path.resolve('msg.txt')); // 勾销监听 }, 2000);});open and close: ...

April 28, 2022 · 3 min · jiezi

关于node.js:node常用内置模块

node罕用内置模块(一)1.nodejs的全局对象global全局对象可看做是全局变量的宿主(局部属性设置了不可枚举),不必点语法,可间接拜访罕用全局变量: __filename:返回正在执行脚本文件的绝对路径__dirname:返回正在执行脚本文件所在目录timer类函数:执行程序与事件循环间的关系process:提供与以后过程互动的接口require:实现模块的加载module、exports:解决模块的导出相似于,在执行.js文件的时候,将js代码放在了一个立刻执行函数外面,并传入了这些变量,所以能够间接应用这些变量了。 // console.log(global);console.log('fileName@',__filename);console.log('dirName@',__dirname);console.log('process.cwd@',process.cwd());console.log('process.env@',process.env);// 默认状况下 this 是空对象 和global不是一个对象console.log('this@',this);(function(){ console.log('fun@',this===global); // true})();2.process模块获取过程信息: // 1.资源:console.log(process.memoryUsage()); // 内存/*{ rss: 20045824, // 常驻内存 heapTotal: 4476928, // 堆内存 heapUsed: 2686544, // 已应用堆内存 external: 889742, // 内部内存 应用的C++的罕用库 arrayBuffers: 9898 // 数组缓冲区大小}*/console.log(process.cpuUsage()); // CPU 零碎与用户操作cpu工夫片的应用状况{ user: 31000,system: 31000 }// 2运行环境:console.log(process.cwd()); // 运行目录console.log(process.version); // node版本console.log(process.versions); // node环境(v8版本、uv版本、zlib版本、openssl版本、ares版本、modules版本)console.log(process.env.NODE_ENV); // 判断是生产环境还是开发环境(undefined,在应用打包工具是,会主动配置)console.log(process.env.PATH); // 环境变量 console.log(process.env.USERPROFILE); // (局部平台应用HOME获取)获取用户目录 写脚手架工具的时候,利用cri命令的时候能够应用console.log(process.arch); // cpu架构console.log(process.platform); // 零碎平台// 3.运行状态: console.log(process.argv); // 启动参数console.log(process.argv0); // 快捷获取参数的第一个参数 execArgvconsole.log(process.pid); // 过程ID ppidconsole.log(process.uptime()); // 运行工夫执行过程操作: ...

April 27, 2022 · 3 min · jiezi

关于node.js:Nodejs-安装及环境配置

一、下载 nodejs 的安装包:下载地址:https://nodejs.org/zh-cn/down...依据本人电脑系统及位数抉择,个别都抉择 windows64 位.msi 格局装置网站上提供的安装包版本过高,也能够通过以下链接获取安装包。 下载到本地后间接双击装置就行,记住装置的门路,我是装置到 C:\Program Files\nodejs 装置胜利后会在零碎环境变量的 path 中主动增加 nodejs 的装置门路,能够先不必关注。关上 cmd 输出 node -v 查看 nodejs 的版本号。 nodejs全套视频学习材料:http://www.atguigu.com/download.shtml 二、扭转 nodejs 的下载依赖包门路装置完 nodejs 后,也同时装置了 npm,npm 是 nodejs 中下载依赖包的命令,治理 nodejs 中的依赖包,下载依赖包时默认下载的门路是 C:\Users\Administrator\AppData\Roaming\npm\node_modules,能够通过 npm root -g 查看。咱们也能够把包的门路放到 nodejs 装置的门路上面,先在装置门路下创立两个文件夹 node_global 、node_cache而后在 cmd 中输出以下命令: npm config set prefix "C:\Program Files\nodejs\node_global" npm config set cache "C:\Program Files\nodejs\node_cache" 三、配置环境变量1、配置零碎环境变量 NODE_HOME C:\Program Files\nodejs 2、配置零碎环境变量 NODE_PATH C:\Program Files\nodejs\node_global\node_modules 3、配置零碎环境变量 CNPM_PATH ...

April 24, 2022 · 1 min · jiezi

关于node.js:nodejs异步IO

nodejs异步IO1.IO理解IO分类(是否立刻获取到调用之后的后果):阻塞IO: 反复调用IO操作,判断IO是否完结(工作轮询:read、select、poll、kqueue、event ports)因为在轮询的过程中,程序再期待IO的后果,对于代码而言,还是同步的成果非阻塞IO: 实现无需判断的非阻塞IO,通过某种信号或者回调的模式传回给以后的代码进行应用文件IO: 放入到node实现的线程池中异步网络IO: 利用到了node的外围库libuv库,可判断所运行的平台,依据平台调用不同的异步IO解决的办法(做到了相似于跨平台的成果) 实现异步IO的过程: 2.为什么要应用异步I/O在不同模式下执行两工作,显然,异步应用的工夫,比同步应用的工夫少 3.事件驱动架构事件轮询是异步IO的实现,对异步IO后果的解决(利用事件驱动、公布订阅、察看则模式),依赖于nodejs的events库;代码层面展现: const EventEmitter = require('events');const emitter = new EventEmitter();// 订阅1emitter.on('event',(result)=>{ console.log('event1 fired'); console.log(result);})// 订阅2emitter.on('event',(result)=>{ console.log('event2 fired');})// 公布emitter.emit('event','event_result');/*后果event1 firedevent_resultevent2 fired*/了解到平时编码中,所写的异步代码(订阅啊事件),回调函数就是事件的处理程序,不过公布事件是由零碎实现的 4.nodejs单线程怎么实现并发:异步非阻塞IO配合事件事件回调告诉运行js代码的主线程是单线程(缩小了多线程切换的cpu开销与内存开销),然而在libuv库中,应用到了node实现的线程池毛病:解决cpu密集型的工作时,无奈体现多核cpu的劣势代码展现单线程解决cpu密集型工作时呈现的阻塞景象: const http = require('http');function sleepTime(time){ const sleep = Date.now() + time * 1000; // 同步代码,等待时间 while(Date.now() < sleep){}; return;}sleepTime(4);const server = http.createServer((req,res)=>{ res.end('server starting ...');});server.listen('8080',()=>{ console.log('服务启动了');})5.nodejs利用场景适宜IO密集型工作解决,nodejs作为中间层,搭建bff层服务器(进步吞吐量,不便解决数据):

April 23, 2022 · 1 min · jiezi

关于node.js:node了解

理解node.js1.nodejs诞生Node之父的Ryan Dahl阻塞式IO是谬误的形式,V8的公布为Node的诞生奠定了松软的根底。JavaScript自身就是单线程的,而且浏览器发动的AJAX申请就是非阻塞的。所以将JavaScript和异步IO以及一个简略的HTTP服务器汇合在一起,就达到一个比拟好的配合。尽管Node的非阻塞模型没有了多线程,但却多出了“回调天堂”问题。Ryan认为Node并不适宜用来开发大规模的服务端利用。相比之下,Go语言(在运行时和操作系统之间所有的IO操作都是非阻塞的,然而它提供给用户的接口却是阻塞式的。)会是更好的抉择。参考文章:https://www.techug.com/post/n... 2.nodejs简介个别称 Node.js 是一个平台,它将多种技术组合起来,让 JavaScript 能够调用一些 C/C++ 的接口,拓展了js语言的性能,让 JavaScript 也能调用零碎接口、或进行后端开发的利用。 node.js工作流程: 3.node.js 根本架构node.js次要分为四大局部:Node Standard Library、Node Bindings、V8、Libuv,架构图如下: Node Standard Library 是 Node 专门提供给开发人员应用的规范库,如 Http, Buffer, fs 等模块。Node Bindings 是沟通 JS 和 C++ 的桥梁,封装 V8 引擎 和 Libuv 的细节,向下层提供根底 API 服务。第三层是撑持 Node.js 运行的要害,由 C/C++ 实现。V8 是 Google 开发的 JavaScript 引擎,提供 JavaScript 运行环境,能够说它就是 Node.js 的发动机。 Libuv 是专门为 Node.js 开发的一个封装库,提供跨平台的异步 I/O 能力.C-ares:提供了异步解决 DNS 相干的能力。http_parser、OpenSSL、zlib 等:提供包含 http 解析、SSL、数据压缩等其余的能力。4.Bindings是个啥?Node Bindings 是沟通 JS 和 C++ 的桥梁,封装 V8 引擎 和 Libuv 的细节,向下层提供根底 API 服务。 ...

April 23, 2022 · 2 min · jiezi

关于node.js:node-报错记录Cannot-find-module-arewethereyetindexjs

一沉睡来美滋滋关上我的项目npm start,居然报错了。 Error: Cannot find module 'D:\Program Files\nodejs\node_modules\npm\node_modules\are-we-there-yet\index.js'.Please verify that the package.json has a valid "main" entry尝试应用 npm -V,居然也报错。啊,这。 看了下报错,说npm的文件夹里短少东东。重新安装下雷同版本的nodejs,复活了。勾选change这个,一路next就能够。

April 22, 2022 · 1 min · jiezi

关于node.js:实现Nest中参数的联合类型校验

前言在nest的dto层对参数进行校验时,某个参数可能有多种类型,遇到这种状况你会怎么解决?本文将跟大家分享这个问题的解决方案,欢送各位感兴趣的开发者浏览本文。 场景概述咱们在进行接口开发时,客户端须要传入一个名为text的字段,它可能是string类型或Array<Object>类型(在TS中咱们把这种关系称之为 联结类型 ),class-validator库中提供了相干的校验注解,那把他们写在一起是否实现相干的校验呢,如下所示: export class AppDto { @ApiProperty({ example: "2022年4月20日批改", description: "备注" }) @IsString() @IsArray() @ValidateNested({ each: true }) @Type(() => TextObjDto) public text!: string | Array<TextObjType>; }TextObjDto的代码如下所示: export class TextObjDto { @ApiProperty({ example: "修复了一些bug", description: "内容" }) @IsString() content!: string; @ApiProperty({ example: "2022-04-20 07:52", description: "创立工夫" }) @IsString() createTime?: string; @ApiProperty({ example: true, description: "是否为新性能标识" }) @IsBoolean() mark?: boolean;}启动我的项目,用postman测试后发现并不好使,传了array类型的数据又要求是string类型,传了string类型的数据又要求是array类型。 留神:嵌套类型的对象验证须要应用@ValidateNested和@Type注解, @Type承受一个回调函数,函数外部须要返回一个用class申明的dto类。解决方案通过一番求助,翻了一圈class-validator的文档,发现没有现成的解决方案。那么,就只能本人拿到参数搞自定义校验了。 在class-transformer这个库中,提供了Transform办法,它承受一个回调函数作为参数,回调函数中提供了一个TransformFnParams类型的参数,其中的value字段就是客户端传过来的参数,咱们只须要对其进行校验即可。 接下来,咱们来看下实现代码,如下所示: export class AppDto { @ApiProperty({ example: "2022年4月20日批改", description: "备注" }) @IsOptional() @Transform(({ value }) => checkTitleKey(value)) public text!: string | Array<TextObjType>;}上述代码中,咱们有一个名为checkTitleKey的校验函数,因为须要本人校验,所以就须要本人把TS的类型校验复刻一遍进去,实现代码如下所示: ...

April 21, 2022 · 2 min · jiezi

关于node.js:将node项目部署到云服务器详细教程

前言: 须要有node我的项目,并且能在本地服务器胜利运行胜利 一、购买云服务器云服务器品种很多,价格都差不多,我这里购买的是ecs计算型云服务器,配置2核4G5M的配置根本就能够运行我的项目。 服务器购买我抉择的是ecs计算型云服务器。购买步骤:进入云服务器官网抉择服务器配置抉择2核4G5M地区尽量抉择国内(选国比较慢,然而不备案域名就能够拜访,国内的服务器必须备案)零碎抉择CentOS7.9-8.2版本就行抉择自定义明码,最好写文档记录,不然忘了又得重置明码全副操作实现当前就付款购买二、连贯云服务器云服务器购买了,咱们须要在本地连接云服务器,这里我应用的是宝塔近程工具 复制云服务器的公网IP关上宝塔近程工具新建连贯输出公网IP输出服务器账号密码命令行呈现 # 示意连贯胜利 三、装置宝塔因为Linux命令很多很杂,宝塔可视化面板能够不便操作与装置利用,用可视化代替命令行(收费) 进入宝塔官网页面,抉择装置办法第一个并复制 Centos装置脚本yum install xxx进入Xshell粘贴装置命令(这里是不能ctrl+cv的,不过能够设置)装置完会显示:外网面板地址、内网面板地址、username、password抉择地址(内网、外网都行),用浏览器关上,输出账号密码就能够进入宝塔面板了如果是后续要进入宝塔面板,只须要进入Xshell,而后输出 bt default即可显示地址这里我曾经装置过Xshell了,无奈演示装置结束的提醒内容。我就演示输出 bt default 的提醒 四、装置对应软件进入面板它会提醒你装置一整套软件,我这里抉择了装置举荐的再去软件商店装置PM2管理器 五、连贯数据库将本地的数据库导入到云服务器中 点数据库,增加数据库设置数据库名、用户名、明码、拜访权限,拜访权限为所有人,而后确认增加完后导入数据,将本地数据库文件 xxxx.sql 导入 六、放行端口须要云服务器放行端口,浏览器能力失常拜访,个别服务器默认放行了全副端口,我能够删除默认放行的全副入方向端口,而后单个放行咱们须要的端口,这样绝对平安一些 点击平安放行8888、3306、80、22、443设置对应端口用处的名字,例如8888为宝塔端口... 七、上传文件将咱们本地须要的文件全副上传到云服务器中 点击文件,找到www/wwwroot根目录将本地文件压缩以下再上传,上传胜利后解压,解压上传容易失落文件 八、批改配置文件本地文件上传到云服务器中,外面的配置文件不一样,须要批改,如端口号、数据库名、ip地址、用户名和明码 config中批改json和app.js配置json中将ip地址改为以后网页的ip地址,端口号改成8888用户名和明码对应下面设置的数据库app.js中将端口号也改为8888九、关上PM2,并启动服务器PM2是node过程管理工具,能够利用它来简化很多node利用治理的繁琐工作,如性能监控、主动重启、负载平衡等,而且应用非常简单不便。咱们须要用PM2来增加并启动服务器。 关上PM2,找到方才的服务器目录启动app.js,设置名称 十、测试服务器这里须要在本地应用postman测试云服务器 关上本地postman找到文档对应的接口将ip和接口更换为刚刚设置的地址和接口胜利示意云服务器设置胜利 node我的项目就胜利部署到云服务器了,这样咱们编写前端时就不必开启开启服务器啦。 最初如果你感觉这篇文章对你有点用的话,麻烦请给咱们的开源我的项目点点star:http://github.crmeb.net/u/defu不胜感激 ! 收费获取源码地址:http://www.crmeb.com PHP学习手册:https://doc.crmeb.com 技术交换论坛:https://q.crmeb.com

April 20, 2022 · 1 min · jiezi

关于node.js:央视新闻-华纳公司在线

微信bi1988094月15日,区委政法委召开“迎盛会、铸虔诚、强担当、创业绩”主题学习宣传教育实际流动动员部署会暨第一次领导小组(扩充)会议,政法委党支部书记武洪同志主持会议,委机关整体党员干部加入会议。 会议传播了市委、市委政法委、区委“迎盛会、铸虔诚、强担当、创业绩”动员部署会的会议精力和工作要求。武洪同志对委机关发展“迎盛会、铸虔诚、强担当、创业绩”主题学习宣传教育实际流动进行部署安顿。 会议强调,一是进步政治站位。委机关整体干部要认真落实市、区委要求,把发展主题学习宣传教育实际流动作为一项重大政治工作,粗浅意识到发展主题学习教育实际流动的重要意义、思维外延,强化虔诚教育,切实把对“两个确立”的粗浅意识转化为做到“两个保护”的口头盲目。二是落实重点工作。紧紧围绕护航党的二十大这一核心工作,认真贯彻落实市委、区委主题实际流动重点工作工作,特地是对“坚定筑牢首都政治‘护城河’”的工作要求,扎实树牢火线意识,发挥战斗精力,强化社会面稳控,勇当党和人民的虔诚卫士。三是增强兼顾筹划。要将主题实际流动与落实政法工作会议各项部署联合起来,与深入拓展党史学习教育成绩联合起来,与坚固深入政法队伍教育整顿成绩联合起来,与落实全面从严管党治警各项工作联合起来,把学习宣传教育成绩转化为鼓足干劲、提气提神、攻坚克难的弱小能源,以优异成绩迎接党的二十大胜利召开。

April 16, 2022 · 1 min · jiezi

关于node.js:如何通过-Node-上传小程序代码不会就看看吧

在小程序后盾获取秘钥和设置白名单服务器IP(微信公众平台-开发-开发设置) 微信公众平台地址:mp.weixin.qq.com 1、获取秘钥 2、设置白名单,白名单填本人的服务器的ip地址,例如:192.168.1.1 装置miniprogram-ci npm install miniprogram-ci --save创立预览文件 // 引入装置的miniprogram-ci包const ci = require('miniprogram-ci');// 创立project对象const project = new ci.Project({ appid: '小程序的appid', projectPath: '小程序代码文件夹(project.config.json所在的文件夹)', privateKeyPath: '小程序后盾获取的秘钥文件地址',})const previewResult = ci.preview({project, desc: 'miniprogram-ci预览', // 小程序形容 setting: { es6: true, // 开启es5转es6}, qrcodeFormat: 'image', // 返回预览二维码文件的格局 qrcodeOutputDest: '二维码文件保留门路', onProgressUpdate: console.log, // 进度更新监听函数})console.log(previewResult)执行预览小程序文件 // preview.js为上传文件的地址node preview.js 创立上传文件 // 引入装置的miniprogram-ci包const ci = require('miniprogram-ci');// 创立project对象const project = new ci.Project({ appid: '小程序的appid', projectPath: '小程序代码文件夹(project.config.json所在的文件夹)', privateKeyPath: '小程序后盾获取的秘钥文件地址',})const uploadResult = ci.upload({project, robot: 8, // ci机器人编号1-30内 version: '1.1.1', // 小程序版本 desc: 'miniprogram-ci上传', // 小程序形容 setting: { es6: true, // 开启es5转es6}, onProgressUpdate: console.log, // 进度更新监听函数})console.log(uploadResult)执行上传小程序文件 ...

April 14, 2022 · 1 min · jiezi

关于node.js:Nodejs从入门到放弃随手笔记一

提前申明:本文皆以本人为视角来记录本人学习node的过程,故不当做教程公布。刚开始初学不乏有认知谬误的中央,请读者斟酌,如有误还望评论区内指出,鄙人定不耻下问虚心求救,一起晋升。 每种语言都有本人的运行环境,什么是运行环境?javaScript这门语言为什么能够在浏览器中运行?换句话说,为什么浏览器能够辨认javascript这门语言的代码?为什么我就不能用java,C++,这种语言来开发网页呢?这样解释的话,浏览器就是javaScript的运行环境。 具体为什么会呈现Node这个货色,那就要说起服务器和数据库I/O性能的问题了,因为服务器和数据库的I/0输入输出模式,导致了这部分为了解决高并发问题优化起来十分艰难,那么怎么晋升web性能呢?只能从传统的客户端到服务器这一头传统的java ,c语言写出的服务器脚本都是多线程,客户端每向服务器发送一个申请,就会调配一个线程来为这个申请服务,而服务器到数据库申请的过程中,这个服务器线程是没事干的。就好比一去餐厅吃饭,餐厅为每一个桌都调配一个服务员,而服务员和你沟通的工夫就仅仅只有点菜的工夫,她把菜单给厨师,厨师在炒菜的期间,她都还在你背后等着菜进去。这样就节约了很多内存资源,双11对电商服务器的压力可想而知。而node是JS的运行环境,JS是单线程,通过异步编程,这样就不会有资源的节约,就好比餐厅只有一个服务员,然而她能够一秒实现对你的服务,超级服务员(你大可不必在这里抬杠)。 你又可能会有疑难,那为什么我不多加几个厨师呢? 这就是服务器和数据库之间交换的硬件性能问题,数据库寄存在硬盘中,硬盘的读取速度是取决于硬件的品质,是事实里存在的硬件,就会有晋升的瓶颈,会有极限,而编程思维是没有限度的,同样一个工作的函数代码能够有不同的写法,情理是一样的。 又或者你能够间接了解成,刚开始的时候,js也就只是用来和浏览器打交道的,然而随着日益的需要,前端人员发现和后端交互的时候还不如本人写接口,于是乎,就有人创造了另外一种运行环境 node.js,你别在node这个英文单词上死钻牛角尖,没必要,你就晓得这货色能够让你用js代码开发后端的相干的货色。 你须要理清这个概念,DOM,BOM这货色可不是js自身这门语言所有的,这可是浏览器环境提供给你更不便的开发页面成果的API。Node说,既然我大哥浏览器环境都给你这么多API了,那我也给你一点吧。然而这里须要咱们思维上有个转变,间接dom,bom都是和浏览器打交道,那些扭转能够直观的在浏览器上展现进去,然而后端就是和数据打交道的,思维上要有转变,不能还依照之前前端的思维来思考这些问题了。 一.模块化思维模块能够是一个.js文件等一些货色,很形象。因为我的学习过程是 三剑客-->react。所以我对es6的模块化比拟相熟,了解node中的这个也比拟容了解承受。然而咱们须要留神的是,node里遵循的是common.js标准,而咱们浏览器端应用的是es6语法,node当初也能够完满反对es6的新的引入或者导出的规定,然而仍有不可代替的中央,比方import必须在头部引入,无奈作为逻辑判断来进入函数外部。 比方if语言,你不能够这样编写你的代码 然而common.js却能够在逻辑判断中按需要引入。 1.2 模块的底层原理我在nodeText文件夹下创立了两个文件 咱们都晓得,在我编写了一个js文件后,它就是能够被当作一个模块来应用,那咱们在nodeOutPut里引入。 这里咱们须要晓得的是,require办法会将那个门路里的js文件内的代码编程成一个对象来引入。通过打印CCC的类型就能够晓得其实是一个对象。这也就解释了为什么能够通过解构赋值的办法引入react的hooks import {useState,useEffect} from 'react'咱们runcode一下,能够看到控制台输入了咱们在Text.js里编写的代码。 留神⚠️:特地重要的概念 在这个nodeText.js模块里,node其实在外层包裹了一个函数,所以在这个外面定义的所有变量都是局部变量,这也就解释了为什么全局对象global身上没有这两个属性。 arguments.calee示意正在执行这个代码的参数,+" "示意让arguments.callee这个被执行的函数toString变成字符串拼接的模式打印进去,后果如下。 外壳的函数一共有五个参数 1.exports是module参数的一个属性,它和module.exports指向同一个对象地址,而module就是这个模块自身,module.exports.AAA= console.log(“a”)也就是裸露进来本人module身上的exports对象里的AAA办法。2.require就解释了为什么你能够间接应用require这个办法而不需引入。3._filename和_dirname很好了解,filenae准确到你这个自身,准确到index.js,而dirname准确到这个文件所在的文件夹。这就解释了为什么别的模块能够通过require('./nodeText')找到该模块。

April 14, 2022 · 1 min · jiezi

关于node.js:Nodejs-Playwright-2Captcha-验证码识别实现自动登陆

原文:https://lwebapp.com/zh/post/b... 需要日常工作当中,为了进步工作效率,咱们可能会写脚本来主动执行工作。有些网站因为须要用户登陆,所以脚本的主动登陆性能必不可少。 不过咱们在登陆网站的时候常常会呈现验证码,验证码的目标就是为了避免机器登陆、自动化脚本操作,那么有没有方法让脚本能自动识别验证码实现登陆呢? 接下来我以 B 站为例给大家解说下,如何解决主动登陆脚本中最要害的验证码问题。 摸索首先须要体验下这个网站的登陆形式,理解下它的验证码类型。 关上 B 站 https://www.bilibili.com/ ,关上控制台,点击登陆,这时候会弹出两头小的登陆框,通常输出完账号和明码,就会弹出验证码框了,咱们猜想验证码的接口此时曾经申请了。 因为验证码的英文是 captcha ,咱们在 network 面板里搜 captcha 发现了一个和验证码相干的接口 https://passport.bilibili.com/x/passport-login/captcha点开看接口返回后果,果然有一些有用的信息,咱们发现验证码类型是 geetest 。 { "code": 0, "message": "0", "ttl": 1, "data": { "type": "geetest", "token": "b416c387953540608bb5da384b4e372b", "geetest": { "challenge": "aeb4653fb336f5dcd63baecb0d51a1f3", "gt": "ac597a4506fee079629df5d8b66dd4fe" }, "tencent": { "appid": "" } }}通过搜寻发现了 B 站应用的验证码服务是 geetest 提供的,国内有很多网站都用的这个服务, geetest 验证码的特点是挪动拼图、按程序抉择文字或者数字。 那么接下来,就来寻找能够辨认 geetest 验证码的方法。 小编理解了市面上提供的验证码解决方案,成果比拟好的根本都是 OCR 服务商,比照之后发现 2Captcha 的服务十分好,解码速度快、服务器连贯稳固、反对多种语言 API、价格公道,小编决定试用下 2Captcha 。 2Captcha 官网接下来就展现应用 Nodejs + Playwright + 2Captcha 来解决 B 站的登陆验证码问题。 ...

April 13, 2022 · 3 min · jiezi

关于node.js:windows升级nodejs版本问题

原文:https://mp.weixin.qq.com/s?__... 微信公众号:毛毛虫的小小蜡笔问题看到网上有个vue的问题,就想着写个vue的demo来验证下。 后果在通过vue cli创立我的项目之后,再执行yarn install命令装置依赖包,发现居然报错了。如下截图所示: 看error的提醒,说的大略是node的版本问题。冀望node的版本是12.22.0等其余版本。但我电脑上的版本却比拟低。如下截图所示:很显著不是它冀望的12.22.0等版本,所以就须要降级node的版本。 降级node.js版本最简略的形式就是到官网,下载稳固版本的安装包。 点击LTS的版本后,下载了node-v16.14.2-x64.msi的安装包。 然而,双击安装包后,发现有个正告提醒!如下截图所示: 看起来是说windows版本问题,我电脑是windows 7。 那怎么办呢?据说能够通过npm装个n包来降级node版本,但执行npm install -g n之后,报错了,n包不反对windows。如下截图所示: 那只能到官网找其余版本的下载来装置了。看刚开始提醒的node版本,那就下载12.22.0版本试试。 下载后,装置没提醒windows版本问题,也能顺利装置胜利。 最初公众号《毛毛虫的小小蜡笔》有疑难和问题,请留言。 如果感觉文章还能够,请点赞或珍藏,谢谢。

April 9, 2022 · 1 min · jiezi

关于node.js:装个Node

这是一个Node.js的装置步骤记录,为什么要装置?因为不装用不了npm呀...好了,上面进入正题bibobibobibobibobibobibobibobibobibobibo... 第一步:下载 这是网址:Node下载(点一下应该能跳过去这里:https://nodejs.org/en/download/)选一个你喜爱的,哦不,对应零碎的 第二步:装置 关上安装包,神奇的界面呈现了 而后...这里当然要批准啦,不然不让用哈 再而后...选一个要装置的目录~ 再再而后...始终Next,直到install~ 呈现了这个,请看-->没错,这是读条界面... 咱就是等条读完Finishi啦! 没有而后了,Over~Over~ 哦,对了,如果要验证装胜利了没有,在cmd黑框框外面输出npm执行后看到一堆货色,就算装置胜利啦!就像这样-->OvO

April 9, 2022 · 1 min · jiezi

关于node.js:设置Nodejs脚本开机自启动

起因本人常常用Typora写货色做记录,有时候想在上班或周末接着写,然而Typora并没有近程同步的性能,所以想写个小工具帮本人做上传同步:服务开机自启动并拉取内容,监听工作库目录有变动则同步到远端。 如果想应用脚本或者快捷命令关上其他软件能够参考举荐一个工作区治理小工具中对于open 命令的形容。Windows 设置开机自启能够参考 Windows设置本人的程序开机主动启动 MacOS 设置服务开机自启动办法1:设置登录项进入零碎偏好设置 -> 用户与群组(账户) -> 登录项 点击下方的+就能够增加登录项,会在开机后主动运行,设置了的开机自启项也会在这里治理。 要留神的是如果应用Node.js脚本作为启动项,须要删除文件后缀并增加可执行权限(否则开机后会应用编辑器关上,而不是执行脚本)。 办法2:扩大坞设置登录关上扩大坞 -> 选项 -> 登录时关上,然而只能针对装置的应用程序。 办法3: Launchd配置Launchd是Mac下用于初始化操作系统的要害过程。通过启动硬盘指定目录下的配置文件,来实现启动工作。 目录形容~/Library/LaunchAgents以后用户登陆后启动的服务/Library/LaunchAgents由管理员定义的用户登陆后启动的服务/Library/LaunchDaemons由管理员定义的守护过程工作项/System/Library/LaunchAgentsMacOS零碎定义的用户工作项/System/Library/LaunchDaemonsMacOS零碎定义的守护过程工作项plist 配置比拟有用的配置关键字: 标签必填阐明Label是标识符,用来示意该工作的唯一性Program是程序名称,用来阐明运行哪个程序、脚本ProgramArguments是同上,与Program二选一或一起应用,只是能够运行多个程序、可带参数WatchPaths否监控门路,当门路文件有变动是运行程序,也是数组RunAtLoad否是否在加载的同时启动StartCalendarInterval否运行的工夫,单个工夫点应用dict,多个工夫点应用 array -> dictStartInterval否工夫距离,与StartCalendarInterval应用其一,单位为秒StandardInPath、StandardOutPath、StandardErrorPath否规范的输入输出谬误文件,这里倡议不要应用.log作为后缀,会打不开外面的信息PM2设置开机自启pm2的startup 命令能够设置nodejs脚本开机自启动。pm2的对不同操作系统进行了不同解决: startup代码 其中对于MacOS的解决也是通过launchd来实现的,会在用户主目录下的Library/LaunchAgents/文件夹中新增一个plist文件: switch(platform) {    ...    case 'macos':    case 'darwin':    case 'launchd':      template = getTemplate('launchd');      destination = path.join(process.env.HOME, 'Library/LaunchAgents/' + launchd_service_name + '.plist');      commands = [        'launchctl load -w ' + destination     ]      break;    default:      throw new Error('Unknown platform / init system name');   }pm2 startup应用的plist模板 ...

April 6, 2022 · 1 min · jiezi

关于node.js:北京市东城区赵海东副区长一行莅临博睿数据参观指导

日前,北京市东城区副区长赵海东一行光临北京博睿宏远数据科技股份有限公司(简称:博睿数据)参观指导,东城园管委会常务副主任于锋池、东城园企业服务处处长孙凤颖、副处长刘佳政相干领导陪同参观。 博睿数据董事长&CEO李凯、博睿数据首席技术官孟曦东及公司财务、人力相干负责人热情接待到访领导并进行座谈。 会议伊始,博睿数据董事长&CEO李凯代表公司对东城区各位领导光临公司参观指导工作,示意热烈的欢送,并向与会领导介绍公司及汇报相干工作状况。 李凯示意,博睿数据自2008年创建以来,专一于利用性能治理(APM)技术畛域;2015年起,博睿数据将翻新重心转向智能运维。凭借博睿数据在技术、市场及产业化等方面的深厚积攒,博睿数据曾经领有近百项软件著作权,27项核心技术。一直为金融、政府、运营商能源、制作、电信、互联网等百行百业的客户提供了数字化解决方案,包含腾讯、阿里巴巴、百度、安全团体、上海证交所、深圳证交所、中国电信等知名企业或政府部门提供服务,已成为国内APM行业的领军企业,同时也于2020年8月成为国内首家在科创板上市的APM公司。将来,博睿数据将在智能运维畛域继续发力,继续更新降级产品外围能力,助力企业数字化转型,让每一家企业都能享受IT智能经营的价值。 与会领导听取了公司介绍后,对公司的倒退以及将来布局的理解进一步加深,对保持“数据为本,赋能商业”的经营理念给予高度认可,对博睿数据10余年专一APM技术畛域,强劲的发展势头予以了充分肯定。随后,领导们别离就APM行业趋势、产业促成、疫情下如何保障经济增长等方面展开讨论。 北京市东城区副区长赵海东示意,“疫情以后,对于各个企业而言,都是一个艰巨的期间,博睿数据作为东城区的高质量企业,一方面要做好维稳工作,一方面要做好疫情防控工作。”同时激励博睿数据进一步加大科技翻新力度,从而为东城区吸引更多科技企业奉献本人的力量。 将来,博睿数据将以北京市东城区各级领导的关心为能源,进一步加大科技翻新力度,一直加强企业外部治理,继续打造中国APM技术的领导力,为社会展示更多丰硕成果,做让政府和社会称心的高科技企业!

April 1, 2022 · 1 min · jiezi

关于node.js:实战linux环境用node自动发送邮件含echarts图赶紧收藏

大家好,我是猫小白,本文带来我最近几天闭关修炼,游走与各大技术论坛最终实现的一个小我的项目,心愿能帮到有雷同需要的同学。我做了个什么货色呢? 其实很简略:通过调用接口把返回的数据转换成表格或者文字定时发送邮件到指定的人!。这个性能干什么用呢? 举个栗子:某位产品负责人很关怀上线的app每天有多少注册的新用户,他可能不会常常关上零碎后盾去查看,只是想每天通过邮件查看,比方在解决其它邮件的时候,顺便看一下,做到成竹在胸。 又或者,某个管理系统的人,须要在他人发动相似订单的时候及时核查信息并且第一工夫审核该订单,那能够通过邮件的形式揭示它。 有的人会想到短信揭示,然而毕竟是免费的。技术前提:家喻户晓、邮件内容是能够退出html字符串的,并且class款式和行内款式都能失效,然而无奈运行javascript代码。所以echarts无奈动静渲染到邮件中,不过咱们能够通过某些伎俩转换成base64,把它作为图片插入到邮件中。梳理下整个程序的实现流程 在之前新建一个空文件夹,运行npm init把我的项目搭建起。 主流程如下: 新建一个html文件,先在本地把款式和布局写好(能够通过live-server等插件本地预览),须要替换的代码片段删除后用变量代替列如:{{body}}、{{date}}、{{img}}。通过axios模块获取接口数据,这里是我共事提供的。通过接口数据拼接响应的字符串并替换模板中的对应变量,例如:<tr><td>balaba</td><td>lalala</td></tr>替换模板中表格的{{body}}通过接口数据渲染出echarts并截图转换为base64,替换img标签的src属性,也就是替换模板中的{{img}}变量。配置并发送邮件实现定时器函数,监听工夫,达到设定的工夫才发送。整个流程看起来比拟繁琐,其实在实现程序的时候写着写着前面的步骤就清晰了,咱们一步一步看如何实现的。 第一步:新建html,写好款式和布局这一步没啥好说的,邮件又不须要多花哨,一个表格一些文字就搞定了,大家分分钟就搞定了。 写好html后,把style标签外面的款式代码和body外面的代码赋值到一个js中导出备用。取名:template.js大抵内容如下(被我删减了一些,看下意思就行): /** * 邮箱模板 */const template = `<div><style> p { font-size: 13px; line-height: 27px; padding: 0; margin: 0; color: #333; } .content { display: flex; /* justify-content: center; */ flex-direction: column; align-items: left; } .img { margin-top: 10px; } table { border: 1px solid rgb(206, 206, 206); border-collapse: collapse; width: 100%; max-width: 500px; margin-bottom: 16px; }</style> <p>各位领导、共事好,</p> <p style="text-indent:30px">{{date}}XXXX统计信息如下:</p> <div class="content"> <div> <table> <thead> <th>表头字段1</th> <th>表头字段2</th> <th>表头字段3</th> </thead> <tbody> {{tbody1}} </tbody> </table> <img src="{{img1}}" alt=""> </div> </div> <p style="text-align: left;margin-top: 10px;"> 统计工夫:{{datelong}} </p>`exports.template = template;留神其中的要害内容用{{变量名}}的形式替换,不便填充本人的内容; 我这里有表格内容的{{tbody1}}、图片{{img1}}还有统计工夫{{datelong}}。 ...

April 1, 2022 · 5 min · jiezi

关于node.js:博客后台管理DAY12

(十二)我的项目性能的实现之文章评论和退出性能创立评论汇合判断用户是否登录,如果用户登录,再容许用户提交评论表单在服务器端创立文章评论性能对应的路由在路由申请处理函数中接管客户端传递过去的评论信息将评论信息存储在评论汇合中将页面重定向回文章详情页面在文章详情页面路由中获取文章评论信息并展现在页面中 BLOG -- 源码目录 └── config -- 配置文件 └── middleware └── loginGuard.js └── model -- 数据库操作 └── comment.js ├── public -- 动态资源 └── route -- 路由 └── admin ├── login.js 登录 └── logout.js 退出 └── home ├── article.js 博客文章 └──comment.js 博客评论 └── home.js 博客 └── views -- 模板 └── home └── common └──header.art 公共头部模板 └── article.art 文章内容模板 └── app.js -- 创立网站服务comment.js 引入mongoose模块,创立汇合规定增加存储每篇文章的aid,关联文章汇合存储uid评论的用户名,关联用户汇合存储评论工夫,内容time content创立评论联合并作为模块成员进行导出// 将评论汇合构造函数进行导入const { Comment } = require('../../model/comment'); module.exports = async (req, res) => { // 接管客户端传递过去的申请参数 const { content, uid, aid } = req.body; // 将评论信息存储到评论汇合中 await Comment.create({ content: content, uid: uid, aid: aid, time: new Date() }); // 将页面重定向回文章详情页面 res.redirect('/home/article?id='+ aid);}login.js ...

March 31, 2022 · 4 min · jiezi

关于node.js:多人后台博客管理DAY08

另一种分页形式:mongoose-sex-page(第三方模块)BLOG -- 源码目录 └── model -- 数据库操作 ├── public -- 动态资源 └── route -- 路由 └── admin --博客治理 └── article.js --文章列表页 └── views -- 模板 └── admin --博客治理页面art模板 └── article.art --文章列表模板 └── app.js -- 创立网站服务article.js 导入mongoose-sex-page(第三方模块)来实现分页 npm install mongoose-sex-page 承受客户端传递的页码// 将文章汇合的构造函数导入到以后文件中const { Article } = require('../../model/article');// 导入mongoose-sex-page模块const pagination = require('mongoose-sex-page');module.exports = async (req, res) => { // 接管客户端传递过去的页码 const page = req.query.page; // 标识 标识以后拜访的是文章治理页面 req.app.locals.currentLink = 'article'; // page 指定当前页 // suze 指定每页显示的数据条数 // display 指定客户端要显示的页码数量 // exec 向数据库中发送查问申请 // 查问所有文章数据 let articles = await pagination(Article).find().page(page).size(2).display(3).populate('author').exec(); // res.send(articles); // 渲染文章列表页面模板 res.render('admin/article.art', { articles: articles });}article.art ...

March 30, 2022 · 1 min · jiezi

关于node.js:多人后台博客管理DAY06

(六)我的项目性能的实现之用户信息删除 BLOG -- 源码目录 └── model -- 数据库操作 ├── public -- 动态资源 └── route -- 路由 └── admin --博客治理 └── user-delete.js --用户分页性能路由 └── admin.js --博客治理页面路由 └── views -- 模板 └── admin --博客治理页面art模板 └── user.art --用户列表页 └── app.js -- 创立网站服务user.art 对删除框增加暗藏域,type=hidden,为暗藏域也增加id找到删除按钮并增加Id,为删除标签增加类名 ,并增加点击事件,次要通过jquery中的来捆绑id增加点击事件将要删除的id值增加到暗藏域中为表单增加提交地址action到delete{{extend './common/layout.art'}}{{block 'main'}} <!-- 子模板的相对路径绝对的就是以后文件 因为它是由模板引擎解析的 而不是浏览器 --> {{include './common/header.art'}} <!-- 主体内容 --> <div class="content"> {{include './common/aside.art'}} <div class="main"> <!-- 分类题目 --> ··· <!-- /分类题目 --> <!-- 内容列表 --> <table class="table table-striped table-bordered table-hover custom-table"> ··· <a href="/admin/user-edit?id={{@$value._id}}" class="glyphicon glyphicon-edit"></a> <i class="glyphicon glyphicon-remove delete" data-toggle="modal" data-target=".confirm-modal" data-id="{{@$value._id}}"></i> </td> </tr> {{/each}} </tbody> </table> <!-- /内容列表 --> <!-- 分页 --> ··· <!-- /分页 --> </div> </div> <!-- /主体内容 --> <!-- 删除确认弹出框 --> <div class="modal fade confirm-modal"> <div class="modal-dialog modal-lg"> <form class="modal-content" action="/admin/delete" method="get"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button> <h4 class="modal-title">请确认</h4> </div> <div class="modal-body"> <p>您确定要删除这个用户吗?</p> <input type="hidden" name="id" id="deleteUserId"> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">勾销</button> <input type="submit" class="btn btn-primary"> </div> </form> </div> </div>{{/block}}{{block 'script'}} <script type="text/javascript"> $('.delete').on('click', function () { // 获取用户id var id = $(this).attr('data-id'); // 将要删除的用户id存储在暗藏域中 $('#deleteUserId').val(id); }) </script>{{/block}}user-delete.js ...

March 30, 2022 · 1 min · jiezi

关于node.js:Nodejs开发心路历程

一、Node.js 全栈开发材料1、前端入门根底 慕课网HTML +CSS入门慕课网JS入门 javascript进阶篇 菜鸟教程html局部 菜鸟教程CSS局部阮一峰js入门 阮一峰es6教程 html中文网JavaScript中文网2、node 后端入门根底 node入门 Linux基础知识mysql数据库常识 数据库事务sequelize中文文档 Express框架官网文档 Koa官网文档 koa框架教程 Egg.js官网 3、深入浅出Node.js-朴灵 链接:https://pan.baidu.com/s/1Aemx...提取码:nbso4、vue学习材料 vue官网文档 视频教程 ) vuex官网文档 vue-router官网文档 axios中文文档 ElementUI官网文档webpack官网文档 webpack5视频教程5、flex布局 flex 布局教程:语法篇 Flex 布局教程:实例篇 flexb布局视频教程 二、JSON1、JSON教程2、JSON.stringfy() 和 JSON.parse()2.1 JSON.stringfy() 将对象、数组转换成 JSON字符串 概述: JSON.stringfy()办法是将一个JavaScript值(对象或者数组)转换为一个 JSON 字符串,如果指定了replacer是一个函数,则能够选择性的替换值,或者如果指定了replacer是一个数组,可选择性的仅蕴含数组指定的属性。 ```js1.转换值如果有toJSON()办法,该办法定义什么值将被序列化。2.非数组对象的属性不能保障以特定的程序呈现在序列化后的字符串中。3.布尔值、数字、字符串的包装对象在序列化过程中会主动转换成对应的原始值。4.undefined 任意的函数以及 symbol 值,在序列化过程中会被疏忽(呈现在非数组对象的属性值中时)或者被转换成 null(呈现在数组中时)。函数、undefined被独自转换时,会返回undefined,JSON.stringify(function(){}) or JSON.stringify(undefined).5.对蕴含循环援用的对象(对象之间互相援用,造成有限循环)执行此办法,会抛出谬误。6.所有以 symbol 为属性键的属性都会被齐全疏忽掉,即使 replacer 参数中强制指定蕴含了它们。7.Date日期调用了toJSON()将其转换为了string字符串(同Date.toISOString()),因而会被当做字符串解决。8.NaN和Infinity格局的数值及null都会被当做null。9.其余类型的对象,包含Map/Set/weakMap/weakSet,仅会序列化可枚举的属性。```例子:```jsJSON.stringify({}); // '{}'JSON.stringify(true); // 'true'JSON.stringify("foo"); // '"foo"'JSON.stringify([1, "false", false]); // '[1,"false",false]'JSON.stringify({ x: 5 }); // '{"x":5}'JSON.stringify({x: 5, y: 6}); // "{"x":5,"y":6}"JSON.stringify([new Number(1), new String("false"), new Boolean(false)]); // '[1,"false",false]'JSON.stringify({x: undefined, y: Object, z: Symbol("")}); // '{}' JSON.stringify([undefined, Object, Symbol("")]); // '[null,null,null]' JSON.stringify({[Symbol("foo")]: "foo"}); // '{}' JSON.stringify({[Symbol.for("foo")]: "foo"}, [Symbol.for("foo")]);// '{}' JSON.stringify( ...

March 29, 2022 · 23 min · jiezi

关于node.js:Nodejs在Linux下的环境搭建及相关命令

一、VMware下载和装置1、下载地址VMware 第一步: 第二步: 第三步:能够默认抉择最新版本 第四步:也能够默认抉择最新版本。如果没有账号必须先注册一个账号能力下载,如果已有账号需登录账号。 2、装置第一步:关上下载好的.exe文件,点击下一步 第二步: 承受协定点击下一步 第三步:可批改装置门路 第四步:能够勾销这两个选项,依据集体需要抉择。 第五步:默认下一步直至装置胜利! 第六步: 软件装置实现后,点击许可证开始进行激活关上软件包中的vmware16永恒激活密钥文本,复制其中一条而后点击激活即可(若生效自行百度即可) ZF3R0-FHED2-M80TY-8QYGC-NPKYF YF390-0HF8P-M81RQ-2DXQE-M2UT6 ZF71R-DMX85-08DQY-8YMNC-PPHV8二、Centos下载和装置1、下载Centos 第一步:点击 Download下载 第二步:依据电脑需要抉择版本 第三步: 轻易选一个国内镜像便可下载(7版本的都可抉择) 第四步:抉择 DVD-2009.iso下载即可。 2、装置Centos7装置步骤 第一步: 双击桌面上的 VMware 按钮关上, 点击微小的 "新建虚拟机" 按钮 第二步:抉择典型, 点击下一步。在这个页面如果零碎没哟匹配到你下载的 linux 安装包, 须要手动抉择下。如果下载好镜像文件抉择下载好的镜像文件即可。 第三步:虚拟机起一个名字 第四步:可批改装置地位 第五步: 磁盘大小默认,个别抉择为:单个文件,方便管理。 第六步: 始终期待即可。 第七步:登录账号(之前设置的明码登录) 三、Xshell和Xftp的下载和装置网上有很多的 Xshell 的破解版、绿色版。然而 Xshell 很多版本存在后门,或上传用户服务器账号密码。这是很可怕的 , 服务器的账号、明码有可能泄露。大家千万千万不要图不便去下载破解、绿色版。一旦公司服务器被黑十分麻烦。同样的公司数据库地址千万不要裸露到公网,如果要裸露公网,肯定要设置白名单。实际上官网针对个人账户是有提供免费版原本下载。 1、 下载Google Xshell 第一步: 第二步:名字轻易输出,邮箱要输出本人的,因为下载链接会发送到该邮箱,勾选两者,能够获取 Xshell 和 Xftp 的链接,因为 Xftp 开发过程也须要用到,倡议勾选。 第三步:之后你的邮箱会收到一封邮件,邮箱中有下载地址,依据下载地址即可下载集体免费版,链接是有有效期的,如果过期的话,大家去官网从新走一遍流程即可 : 2、装置第一步:点击下一步 第二步:抉择收费 第三步:承受协定,下一步 第四步:自定义装置门路 ...

March 29, 2022 · 3 min · jiezi

关于node.js:Nodejs安装及配置

Node.js 下载本文以node.js 16.14.2版本做演示,此版本要求操作系统为win8以上,如操作系统为win7,择可采纳 12.18.4版本(亲测)或者采纳其它12以下版本皆可 Node.js 装置node.js简略装置下载实现后,双击运行下安装包,开始装置,始终无脑装置,始终点 next 即可,装置门路默认事在 C:\Program Files 下,当然这里也能够自定义批改装置门路,然而对于老手来讲,十分十分不倡议装置实现后,咱们装置的node.js会主动帮忙咱们配置环境变量。测试装置时候装置胜利!关上cmd窗口,执行 node -v 命令,查看node.js版本 node -vv16.14.2执行 npm -v 命令,查看npm版本 npm -v8.5.0如图所示: 批改全局依赖包下载地位默认状况下,咱们在执行 npm install -g XXXX 下载全局包时,这个包的默认寄存门路为 C:\Users\用户名\AppData\Roaming\npm\node_modules这里咱们也能够通过 cmd 指令 npm root -g 查看 npm root -gC:\Users\86186\AppData\Roaming\npm\node_modules然而因为咱们C盘存储的空间无限,有时咱们不想将全局包放在这里,咱们能够本人定义寄存目录,在 cmd 狂口下能够执行以下两条命令批改默认门路: npm config set prefix "D:\Software\develop\node\node_global"npm config set cache "D:\Software\develop\node\node_cache"或者关上 D:\Software\develop\node\node_modules\npm.npmrc批改如下配置: prefix =C:\node\node_globalcache = C:\node\node_cacheNode.js 配置

March 29, 2022 · 1 min · jiezi

关于node.js:Nodejs中callbackasync-awaitPromisepromisify

一、回调函数(callback)1、概念A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.翻译:回调函数是作为参数传递给另一个函数的函数,在父函数实现后执行。2、例子阐明var fs = require("fs");var a function f(x) { console.log(x)} function writeFile() { fs.writeFile('input01.txt', 'www.baidu.com', function (err) { if (!err) { console.log("文件写入结束!") a = 1 } });} a = 0writeFile()f(a)输入后果:0文件写入结束!代码阐明:设置一个全局变量 a = 0,后执行writeFile函数(也就是写入一个文件input01.txt),这个函数外面有一行c = 1,函数执行结束之后再跳进去调用f()函数,f()函数,就是把打印一个变量。 依照 “失常” 逻辑,首先 a=0,而后调用writeFile函数,该函数外面有一句a = 1,最初再调用f(a),又因为调用writeFile()是在f(a)之前,所以 a=1 这条语句必定是会被执行到,那么后果应该是打印1,后果居然是0,明明咱们在writeFile函数里咱们从新对 a 进行了赋值,为什么后果还是0呢? 因为程序运行到writeFile()这一行的时候,是一个比拟耗时的IO操作,JS碰到这种操作并不会停在原地始终期待直到函数执行结束,而是间接运行下一条代码(即f(a)),而此时 a = 1这一行代码其实并没有被执行到,所以打印进去的后果还是0 ! ...

March 28, 2022 · 7 min · jiezi

关于node.js:构建千万级高可用企业级Nodejs应用一起无mi

node.js 是什么?download:https://www.sisuoit.com/2747.... 复制下崽ZY:https://www.sisuoit.com/2747.html官网的话:Node.js 是一个 基于 Chrome V8 引擎 的 JavaScript 运行环境。Node.js 应用了一个 事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 初看这段话,每一个字都意识,然而组合在一起就有点懵了,可能就是因为其中的几个关键词(基于 Chrome V8 引擎、事件驱动、非阻塞式 I/O )了,然而咱们一开始学习的话是不必立即就搞清楚这几个专业名词的意思。Chrome 咱们都很相熟,日常开发根本都是用 Chrome 开发调试的,那么在 Node.js 里运行 JavaScript 和在 Chrome 里运行 JavaScript 有什么不同吗? 答案是在 Node.js 里写 JS 和在 Chrome 里写 JS,简直没有什么不一样。 那简直没有不一样就是还有一些不一样的,那不一样在哪里呢? Node.js 没有浏览器的一些 API,如 document、window 等;加了很多属于 Node.js 本身的 API,如 process、__dirname、__filename。 而对于开发者来说,Node.js:在 Chrome 里写 JavaScript 是管制浏览器。Node.js 能够让咱们用相似的形式,管制整个计算机。 Node.js 能用来做什么? 能够用来做 Web 服务开发 通过服务端渲染(SSR)能够优化搜索引擎和首屏加载速度前端端同构(前后端用同一套代码),能够大大降低开发成本和保护老本 构建工作流,应用 Node.js 做 JS 构建工具,是很保险的抉择。 因为构建工具不会永远不出问题,也不会永远满足需要 自定义模块,能够应用 Node.js 做简单的本地利用;而大型利用须要给使用者自定义模块的能力 ...

March 27, 2022 · 2 min · jiezi

关于node.js:构建千万级高可用企业级Nodejs应用吾爱

下栽地止:https://lexuecode.com/4435.htmlNode.js利用开发介绍Node.js 是一个开源与跨平台的 JavaScript 运行时环境 在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术进步性能 能够了解为 Node.js 就是一个服务器端的、非阻塞式I/O的、事件驱动的JavaScript运行环境 Node.js优缺点长处: 解决高并发场景性能更佳适宜I/O密集型利用,值的是利用在运行极限时,CPU占用率依然比拟低,大部分工夫是在做 I/O硬盘内存读写操作 因为Nodejs是单线程,带来的毛病有: 不适宜CPU密集型利用只反对单核CPU,不能充分利用CPU可靠性低,一旦代码某个环节解体,整个零碎都解体 构建千万级高可用企业级Node.js利用实战 - Node.js内存治理Node.js内存治理不同于PHP这样的平台,Node.js利用是一个始终运行的过程。尽管这种机制有很多的长处,例如在配置数据库连贯信息时, 只须要建设一次连贯,便能够让所有的申请进行复用该连贯信息,但可怜的是,这种机制也存在缺点。 然而,首先咱们还是来理解一些Node.js基本知识。V8的内存管理模式一个运行的程序通常是通过在内存中调配一部分空间来示意的。这部分空间被称为驻留集(Resident Set)。 V8的内存管理模式有点相似于Java虚拟机(JVM),它会将内存进行分段: 代码 Code:理论被执行的代码栈 Stack:包含所有的携带指针援用堆上对象的值类型(原始类型,例如整型和布尔),以及定义程序控制流的指针。堆 Heap:用于保留援用类型(包含对象、字符串和闭包)的内存段在Node.js中,以后的内存应用状况能够轻松的应用process.memoryUsage进行查问, 实例程序如下: var util = require('util');console.log(util.inspect(process.memoryUsage));这将会在控制台产生如下后果: { rss: 4935680, heapTotal: 1826816, heapUsed: 650472}正如咱们所看到的,垃圾收集是个非常复杂的过程,并且即便代码没有问题也有可能会导致内存透露。 通过应用v8(和chrome开发者工具)提供的一些开箱即用的性能,可能帮忙咱们定位问题的源头, 如果你将这种机制构建到你的利用内,这将会十分有助于你发现和修复问题。 当然,如果你问我下面的代码如何修复,其实十分的简略,只有在函数的最初加上一行theThing = null;即可。 构建千万级高可用企业级Node.js利用实战 - 日志治理装置 log4js 模块npm i log4js -S<br/> log4js 官网简略示例在 middleware/ 目录下创立 mi-log/demo.js,并贴入官网示例代码: var log4js = require('log4js');var logger = log4js.getLogger();logger.level = 'debug';logger.debug("Some debug messages");<br/> ...

March 27, 2022 · 2 min · jiezi

关于node.js:nodejs进阶之旅2使用koa2mysql-实现列表数据分页

1.展现成果(分页) 2.分页次要字段分页次要字段包含 pageSize 每页条数、pageNum 第几页、startRow 以后开始页编号、endRow 以后完结页编号、total 总数量。次要是依据前端分页的参数,进行解决后,返回前端正确的数据,其实是一个很常见且简略的性能。然而是十分也是十分重要的。 pageSize 每页条数pageNum 第几页startRow 以后开始页编号endRow 以后完结页编号total 总数量计算 3.startRow 和 endRow封装成一个函数 /* 分页公共函数*/module.exports = handlePages = (pageNum, pageSize, total) => { let startRow = total > 0 ? ((pageNum - 1) * pageSize + 1) : 0; let endRow = pageNum * pageSize <= total ? pageNum * pageSize : total; return { pageNum, pageSize, recordCounts:total, startRow, endRow }}4.接口函数中应用该函数从前端传参中获取,分页所须要的数据。 let { nickname, name, role, pageSize, pageNum } = ctx.request.body; //此处进行解决 let pageNum1 = (pageNum - 1) * pageSize//获取用户信息列表async getAllUserList(ctx) { let { nickname, name, role, pageSize, pageNum } = ctx.request.body let res = [] let pageNum1 = (pageNum - 1) * pageSize let total = (await User.getAllUserListTotal())[0].recordCounts if (!nickname && !name && !role) { res = (await User.getAllUserListNotCond(pageSize, pageNum1)) } else { res = (await User.getAllUserList(nickname, name, role, pageSize, pageNum1)) } ctx.body = { code: 0, data: res.map(v => { if (v.password) { delete v.password } return v }), //分页所有的参数 ...handlePages(pageNum, pageSize, total) } }5.分页中的MySql语句依据分页查询数据库的数据//依据分页查问用户列表async getAllUserListNotCond(pageSize, pageNum) { return await query(`SELECT * FROM user LIMIT ${pageNum},${pageSize}`)}mySql获取数据库数据总条数//获取用户信息列表的总条数async getAllUserListTotal() { return await query(`SELECT COUNT(*) as recordCounts FROM user`)}对于mySql的COUNT()函数作用:COUNT() 函数返回匹配指定条件的行数。 ...

March 26, 2022 · 1 min · jiezi

关于node.js:NodejsCOMMONJS-规范

ECMAScript 规范的缺点没有模块零碎规范库较少没有标准接口不足管理系统模块化如果程序设计的规模达到了肯定水平,则必须对其进行模块化 。模块化 能够有多种形式,但至多 应该 提供可能将代码宰割为多个源文件的机制 。CommonJS 的模块 性能能够帮咱们解决该问题。CommonJS 标准CommonJS 标准的提出,次要是为了补救当前 JavaScript 没有 模块化 规范 的 缺点 。CommonJS 标准为 JS 指定了一个美妙的愿景,心愿 JS 可能在任何中央运行 。CommonJS 对模块的定义非常简略:– 模块援用– 模块定义– 模块标识模块 援用在标准中,定义了 require() 办法,这个方法接手模块标识,以此将一个模块引入到以后运行环境中。模块援用的示例代码:– var math = require('math');模块定义在运行环境中,提供了 exports 对象用于导出以后模块的办法或者变量,并且它是唯一的导出的进口。在模块中还存在一个 module 对象,它代表模块本身,而 exports 是 module 的属性。在 Node 中一个文件就是一个模块。模块定义exports . xxx = function () {};module . exports = {} ;模块标识模块 标识 其实就是模块的名字,也就是传递给 require() 办法的参数,它必须是合乎驼峰命名法的字符串,或者是以 .、 .. 结尾的相对路径、或者绝对路径。模块的定义非常简略,接口也非常简洁。每个模块具备独立的空间,它们互不烦扰,在援用时也显得干净利落。Node 的模块实现Node 中尽管应用的是 CommonJS 标准,然而其本身也对标准做了一些取舍。在 Node 中引入模块,须要经验如下 3 个步骤:– 路径分析– 文件定位– 编译执行在 Node 中,模块分为 三 类:一类是底层由C++ 编写的 内建模块 ,一类是 Node 提供的 核心模块 ;还有一类是用户编写的模块,称为 文件模块 。包 packageCommonJS 的包标准容许咱们将一组相干的模块组合到一起,造成一组残缺的工具。CommonJS 的包标准由 包构造 和 包形容文件 两个局部组成。包构造– 用于组织包中的各种文件包形容文件– 形容包的相干信息,以供内部读取剖析包构造包实际上就是一个压缩文件,解压当前还原为目录。符合规范的目录,应该蕴含如下文件:– package.json 形容文件– bin 可执行二进制文件– lib js 代码– doc 文档– test 单元测试包形容文件包形容文件用于表白非代码相干的信息,它是一个 JSON 格局的文件 – package.json ,位于包的根目录下,是包的重要组成部分。package.json 中的字段– name 、 description 、 version 、 keywords 、maintainers 、 contributors 、 bugs 、licenses 、 repositories 、 dependencies 、homepage 、 os 、 cpu 、 engine 、 builtin 、directories 、 implements 、 scripts 、 author 、bin 、 main 、 devDependencies 。NPM(Node Package Manager)CommonJS 包标准是实践, NPM 是其中一种实际。对于 Node 而言, NPM 帮忙其实现了第三方模块的公布、装置和依赖等。借助 NPM ,Node 与第三方模块之间造成了很好的一个生态系统。NPM 命令npm – v– 查看版本npm– 帮忙阐明npm search 包名– 搜寻模块包npm install 包名– 在当前目录装置 包npm install 包名 – g– 全局模式装置 包npm remove 包名– 删除一个 模块npm install 文件门路– 从本地装置npm install 包名 – registry= 地址– 从镜像源装置npm config set registry 地址– 设置镜像源Buffer( 缓冲区 )从构造上看 Buffer 十分像一个数组,它的元素为 16 进制的两位数。实际上一个元素就示意内存中的一个字节。实际上 Buffer 中的内存不是通过 JavaScript调配的,而是在底层通过 C++ 申请的。也就是咱们能够间接通过 Buffer 来创立内存中的空间。Buffer 的操作应用 Buffer 保留字符串创立指定大小的 Buffer 对象let str = " 你好 atguigu";let buf = Buffer.from(str , "utf -8") ;let buf3 = Buffer.alloc( 1024*8 )Buffer 的转换Buffer 与字符串间的转换– 反对的编码 :ASCII 、 UTF - 8 、 UTF - 16LE/UCS - 2 、 Base64 、Binary 、 Hex– 字符串转 BufferBuffer.from(str , [encoding]);– Buffer 转字符串buf.toString([encoding] , [start] , [end]);写入操作向缓冲区中写入字符串– buf.write(string [, offset[, length]][, encoding ])替换指定索引地位的数据– buf[index ]将指定值填入到缓冲区的指定地位– buf.fill(value [, offset[, end]][, encoding ])读取 操作将缓冲区中的内容,转换为一个字符串返回– buf.toString ([encoding[, start[, end ]]])读取缓冲区指定索引的内容– buf[index ]其余操作复制缓冲区– buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])对缓冲区切片– buf.slice([start[, end ]])拼接缓冲区– Buffer.concat(list[, totalLength])fs (文件系统)在 Node 中,与文件系统的交互是十分重要的,服务器的实质就将本地的文件发送给近程的客户端Node 通过 fs 模块来和文件系统进行交互该模块提供了一些标准文件拜访 API 来关上、读取、写入文件,以及与其交互。要应用 fs 模块,首先须要对其进行加载– const fs = require("fs");同步和异步调用fs 模块中所有的操作都有两种模式可供选择同步 和 异步 。同步文件系统会 阻塞 程序的执行,也就是除非操作结束,否则不会向下执行代码。异步文件系统 不会阻塞 程序的执行,而是在操作实现时,通过回调函数将后果返回。关上和敞开文件关上文件– fs.open(path, flags[, mode], callback )– fs.openSync(path, flags[, mode])敞开文件– fs.close(fd, callback )– fs.closeSync(fd)关上状态 ...

March 23, 2022 · 3 min · jiezi

关于node.js:Bug-ReferenceError-AbortController-is-not-defined

背景node server 提供 ipfs 文件上传服务 源码const { create, globSource } = require('ipfs-http-client');this.ipfs = create({ host: host, port: port, protocal: protocal });async addAll(files) { let addOptions = { pin: true, // wrapWithDirectory: true, timeout: 10000 }; try { let res = [] for await (const result of this.ipfs.addAll(files, addOptions)) { res.push({ path: result.path, size: result.size }) } return res } catch (error) { throw error }}调用 addAll() 办法提醒谬误 ReferenceError: AbortController is not defined起因AbortController 对 node 版本有要求,要求 v16.xx.xx,所以只须要降级 node 版本即可。 ...

March 23, 2022 · 1 min · jiezi

关于node.js:构建千万级高可用企业级Nodejs应用wumi

download:构建千万级高可用企业级Node.js利用备链:https://www.sisuoit.com/2747.html 线程池执行流程想要真正的理解线程池的执行流程,就得先从线程池的执行办法 execute() 说起,execute() 实现源码如下: public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); // 当前工作的线程数小于外围线程数 if (workerCountOf(c) < corePoolSize) { // 创立新的线程执行此工作 if (addWorker(command, true)) return; c = ctl.get(); } // 查看线程池是否处于运行状态,如果是则把工作增加到队列 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // 再次检线程池是否处于运行状态,避免在第一次校验通过后线程池敞开 // 如果是非运行状态,则将刚退出队列的工作移除 if (! isRunning(recheck) && remove(command)) reject(command); // 如果线程池的线程数为 0 时(当 corePoolSize 设置为 0 时会产生) else if (workerCountOf(recheck) == 0) addWorker(null, false); // 新建线程执行工作 } // 外围线程都在忙且队列都已爆满,尝试新启动一个线程执行失败 else if (!addWorker(command, false)) // 执行回绝策略 reject(command);}从上述源码咱们能够看出,当工作来了之后,线程池的执行流程是:先判断以后线程数是否大于外围线程数?如果后果为 false,则新建线程并执行工作;如果后果为 true,则判断工作队列是否已满?如果后果为 false,则把工作增加到工作队列中期待线程执行,否则则判断以后线程数量是否超过最大线程数?如果后果为 false,则新建线程执行此工作,否则将执行线程池的回绝策略, ...

March 22, 2022 · 2 min · jiezi

关于node.js:初识ReactHook-useEffect

要弄清楚这个钩子函数,你首先须要理解react的生命周期原理。 我间接放这张图必定会有老手间接傻眼,这什么鬼玩意啊?因为我刚学到生命周期的时候也是一脸懵逼,通过理论例子来看! 上面是我集体博客首页左侧轮播图的成果实现,手机端成果暗藏了,手机端看不到成果。举荐电脑端看一下。:https://hanzhenfang.vercel.app/https://hanzhenfang.vercel.app/ 刚学到这里的时候,我第一反馈是简略,我用uesState这个钩子不就行了吗?  是,谁去调用呢? 你这个办法写在这里,没人用啊?你说,我加个按钮不就行了吗? 是,你加个按钮能够点击一下而后开始实现换图片的成果,然而客户需要就是你进去网页图片主动就换,你怎么办呢? 首先咱们要有一个概念,咱们是须要用户点击博客页面,图片就随着工夫开始变动的。 很遗憾,单纯的useState是实现不了工作的。 这时候咱们就须要用到相似于class组件里的 componentDidMount 不得不说React在起名字的时候真的是把语义话做到了极致。Did,有点英语常识的都晓得did是过来式,组件didMount,组件曾经挂载好了 大白话就是 我组件曾经渲染好了,你须要我干什么?巧了嘛,我须要你帮我运行我的SetInterval啊 然而忽然回过神来,那是人家类组件的专属钩子函数,咱们是函数组件啊。别怕,useEffect来了。useEffect接管两个参数(一个参数是你心愿在页面渲染实现当前立刻执行的函数,第二个是参考对象)如果你写入空数组,那么useEffect就相当于只执行一次,因为参考对象空数组永远也不会发生变化,如果你写了count,那么你的意思就是count更新,就会调用useEffect。这时候就会陷入一个误区。为了不便看,我革除了一部分内容,前面再讲。  ok,咱们把刚刚写好的函数放进去,好了,能够失常执行了。刚开始我也是这样想的,网上的教程视频说的须要革除计时器,我就在想,我革除干嘛啊,这不是曾经能够满足我的需要了吗?当我本人写博客页面的时候,我才晓得这是为什么。咱们要晓得react是一个单页面利用,我在代码中加了一个console.log("计时器还在运行")  这时候起来没什么  可当我点进去主页的时候,你会发现浏览器报错了,它说一个我的计时器还在运行,然而这个组件曾经被卸载了。这在理论工作当中会产生一些内存透露的危险。  那咋办呢?咱们心愿在咱们的计时器卸载的时候,能够革除这个计时器,办法也非常简单,那就是在计时器的外部 给他返回一个革除计时器的函数不就行了吗? 你可能会有疑难,这effect执行不就刚开始执行起来就马上卸载了吗? react是十分贴心的帮你主动解决在effect中的第二个return语句,它会在组件第二次更新的时候主动调用,(或者组件卸载的时候才会调用,return里的函数相当于类组件里的componentWillUnMount。)它并不会在页面实现当前马上调用。 什么是组件第二次更新呢?为了演示,第二个参数批改为count,意思为 我批改了count,就会从新调用一次effect,就相当于如果第二个参数是一个变动的值,那么useEffect就相当于变成了componentDidUpdate,我更新完了,你须要我做什么? 接下来咱们看控制台怎么输入。你会发现第二个“计时器被卸载”并不会执行。  它很智能的在实现更新后主动革除了上一个计时器而后从新开启了新的计时器!!  至此,useEffect曾经实现了类生命周期的大部分性能。

March 22, 2022 · 1 min · jiezi

关于node.js:通过Laragon配置开发环境

laragon软件是一个集成的php开发环境软件。默认装置了WAMP所需的所有软件。能够疾速搭建一个php的运行环境。同时本软件将默认装置Composer(用于装置Thinkphp),Git(用于版本控制),Nodejs(用于装置和编译Vue我的项目),Yarn(用于装置和编译Vue我的项目) 下载安装:点击这里下载laragon软件 下图所示:应用默认装置地位即可。 下图所示:选中默认选项即可。下图所示:间接装置即可。下图所示:装置中下图所示:装置实现后重启电脑。如下图所示。点击启动所有,能够启动默认装置的软件。 点击右上侧设置图标,能够进行软件设置。 如下图所示,能够设置语言,主动运行等。 如下图所示,能够操作的都是默认装置的软件。能够抉择apache或者nginx作为Web服务。 关上laragon的装置目录中的bin目录,能够看到更多的曾经装置的软件。 如下图所示,能够疾速装置更多的软件。这些软件就能够满足Thinkphp + Vue的开发环境要求。 为了可能在命令行中应用这些命令,咱们须要配置环境变量。如下图所示,抉择零碎变量中的Path 为了可能反对本地装置、编译和开发Thinkphp ( php , composer ) Vue (node) 如果是应用nginx作为本地Web服务,可能须要批改Laragon的默认配置模板。须要批改如下几个文件。 须要将配置模板文件中的代码进行替换。# 被替换的局部#location / {# try_files $uri $uri/ /index.php$is_args$args;# autoindex on;#}# 替换成上面的代码location / { if (!-e $request_filename){ rewrite ^(.*)$ /index.php?s=$1 last; break; }}验证装置:如果执行下列的命令,失去相似的后果,阐明命令行中能够失常运行必要的命令了,能够持续向下前面学习。

March 22, 2022 · 1 min · jiezi

关于node.js:构建千万级高可用企业级Nodejs应用

download:构建千万级高可用企业级Node.js利用node.js爬虫前端同学可能向来对爬虫不是很感冒,感觉爬虫须要用偏后端的语言,诸如 php , python 等。当然这是在 nodejs 前了,nodejs 的呈现,使得 Javascript 也能够用来写爬虫了。因为 nodejs 弱小的异步个性,让咱们能够轻松以异步高并发去爬取网站,当然这里的轻松指的是 cpu 的开销。 要读懂本文,其实只须要有能看懂 Javascript 及 JQuery简略的nodejs根底http 网络抓包 和 URL 根底Nodejs做爬虫的优劣首先说一下node做爬虫的劣势第一个就是他的驱动语言是JavaScript。JavaScript在nodejs诞生之前是运行在浏览器上的脚本语言,其劣势就是对网页上的dom元素进行操作,在网页操作上这是别的语言无法比拟的。 第二就是nodejs是单线程异步的。听起来很奇怪,单线程怎么可能异步呢?想一下学操作系统的时候,单核cpu为什么可能进行多任务处理?情理也是相似,在操作系统中过程对CPU的占有进行工夫切片,每一个过程占有的工夫很短,然而所有过程循环很屡次,因而看起就像是多个工作在同时解决。js也是一样,js里有事件池,CPU会在事件池循环解决曾经响应的事件,未解决完的事件不会放到事件池里,因而不会阻塞后续的操作。在爬虫上这样的劣势就是在并发爬取页面上,一个页面未返回不会阻塞前面的页面持续加载,要做到这个不必像python那样须要多线程。 其次是node的劣势首先是异步并发上。解决的好很不便,解决的不好就会很麻烦。例如要爬取10个页面,用node不做异步解决话,那返回的后果可不肯定是按1、2、3、4……这个程序,很可能是随机。解决的方法就是减少一个页面的序列戳,让爬取的数据生成csv文件,而后从新排序。 第二个是数据处理上的劣势,这点是不如python的,如果只是单纯的爬数据,用node当然很好,然而如果用爬来的数据持续做统计分析,做个回归剖析聚类啥的话,那就不能用node一步到底了。 如何用nodejs做爬虫上面就要说一下如何用nodejs做爬虫了1、初始化我的项目文件在对应的我的项目文件夹下执行npm init来初始化一个package.json文件 2、装置request和cheerio依赖包request听起来很相熟吧,跟python里request性能一样。它的性能就是建设起对指标网页的链接,并返回相应的数据,这个不难理解。 cheerio的性能是用来操作dom元素的,他能够把request返回来的数据转换成可供dom操作的数据,更重要的cheerio的api跟jquery一样,用$来选取对应的dom结点,是不很不便?对一个前端程序员来说,这比python的什么xpath和beautisoup不便了不晓得多少啊哈哈 装置命令也很简略: 别离是npm install request --save 和 npm install cheerio 3、引入依赖包并应用接下来就用request , fs和cherrio写一个爬虫吧! 首先引入依赖模块 var http=require("http"); //网络申请var fs=require("fs"); //操作文件,读写文件var cheerio=require("cheerio"); //扩大模块注:cheerio 模块是第三方模块,须要进行装置:npm install cheerio --save

March 21, 2022 · 1 min · jiezi

关于node.js:构建千万级高可用企业级Nodejs应用

download:构建千万级高可用企业级Node.js利用一、网络层面 DNS预解析概念DNS-prefetch 是一种 DNS 预解析技术。它会在请求跨域资源之前,事后解析并进行DNS缓存,以缩小真正请求时DNS解析导致的请求提早。对于打开蕴含有许多第三方连接的网站,成果显著。实操增加ref属性为“dns-prefetch”的link标签。一般放在在html的head中。复制代码href的值就是要预解析的域名,对应前面要加载的资源或用户有可能打开链接的域名。备注同理,也有“ TCP/IP预连接”,叫preconnect。参考资料中有完整的描述。利用阅读器缓存概念阅读器缓存是阅读器存放在本地磁盘或者内存中的请求后果的备份。当有雷同请求进来时,间接响应本地备份,而无需每次都从原始服务器获取。这样不只晋升了客户端的响应效率,同时还能缓解服务器的拜访压力。其间,约定何时、如何使用缓存的规定,被称为缓存策略。分为强缓存和协商缓存。整个缓存执行的过程大抵如下:①. 请求发动,阅读器判断本地缓存,如果有且未到期,则命中强缓存。阅读器响应本地备份,状态码为200。控制台Network中size那一项浮现disk cache;②. 如果没有缓存或者缓存已过期,则请求原始服务器询问文件是否有变动。服务器根据请求头中的相干字段,判断目标文件新鲜度;③. 如果目标文件没变更,则命中协商缓存,服务器设置新的过期工夫,阅读器响应本地备份,状态码为304;④. 如果目标文件有变动,则服务器响应新文件,状态码为200。阅读器更新本地备份。上述过程有几个关键点如何判断缓存是否过期?阅读器读取缓存的请求后果中响应头的Expires 和Cache-Control,与以后工夫进行比较。其中,Expires是HTTP 1.0的字段,值是一个是相对工夫。Expires: Tue, 18 Jan 2022 09:53:23 GMT复制代码比较相对工夫,有一个弊病,它依赖计算机时钟被正确设置。为理解决这个问题,HTTP1.1 新增了Cache-Control字段,它的值是一个是绝对工夫。Cache-Control: max-age=60 //单位是秒复制代码 如何判断文件是否变动?首先可能通过比较 最初修改工夫。// 缓存后果的 响应头Last-Modified: Mon, 10 Jan 2022 09:06:14 GMT// 新请求的 请求头If-Modified-Since: Mon, 10 Jan 2022 09:06:14 GMT复制代码阅读器取出缓存后果中Last-Modified的值,通过If-Modified-Since上送到服务端。与服务器中目标文件的最初修改工夫做比较。再者可能通过比较 Etag。 Etag实体标签是附加到文档上的任意标签(引用字符串)。它们可能蕴含了文档的序列号或版本名,或者是文档内容的校验和及其他指纹信息。当发布者对文档进行修改时,会修改文档的实体标签来说明这是个新的版本。 从响应头的ETag取值,通过请求头的If-None-Match上送,与服务器目标文件的Etag标签比对。// 缓存的 响应头ETag: "61dbf706-142"// 上送的 请求头If-None-Match: "61dbf706-142"复制代码和下面一样,新增的字段也是为理解决前一种打算的某些缺点: 有些文档可能会被周期性地重写(比如,从一个后盾过程中写入),但实际蕴含的数据经常是一样的。尽管内容没有变动,但修改日期会发生变动。有些文档可能被修改了,但所做修改并不重要,不需要让世界范畴内的缓存都重装数据(比如对拼写或正文的修改)。有些服务器无奈准确地判定其页面的最初修改日期。有些服务器提供的文档会在亚秒间隙发生变动(比如,实时监视器),对这些服务器来说,以一秒为粒度的修改日期可能就不够用了。 如果两个版本的字段同时存在,怎么办?出于阅读器兼容方面的考虑 ,一般两组字段会被同时使用。他们没有优先级一说,取并集。同时出现时,只有当两个条件都满足,才会命中相应缓存。 实操缓存是web服务器和阅读器的核心能力,支流的web服务框架 nginx、koa-static等都内置有上述缓存策略的实现。开箱即用,无需额定编程或配置。以Nginx举例。强缓存的配置字段是expires,它接受一个数字,单位是秒。server {listen 8080;location / {root /Users/zhp/demo/cache-koa/static;index index.html; # 注意try_files会导致缓存配置不失效try_files $uri $uri/ /index.html;expires 60;}}复制代码实际工作中确实配置一下就好了,但这体现不出什么学识点。为了加深印象,我这用koa简陋的模拟了一下,算是对下面那些学识点的考据。上面是一个极简的动态资源服务,不带缓存的。app.use(async (ctx) => { // 1.根据拜访路径读取指定文件 const content = fs.readFileSync(./static${ctx.path}, "utf-8"); // 2.设置响应ctx.body = content;});复制代码这种情况,无论拜访几次都是不进缓存的。现在,在响应头加上强缓存所需的Exprise和Cache-Control字段app.use(async (ctx) => { // 1.根据拜访路径读取指定文件 const content = fs.readFileSync(./static${ctx.path}, "utf-8"); // 2.设置缓存 ctx.response.set("Cache-Control", "max-age=60"); ctx.response.set('Exprise', new Date(new Date().getTime()+60*1000));// 3.设置响应ctx.body = content;});复制代码查看Network,响应头会多出上面两个字段,且间隔60秒内的请求会走缓存,符合预期。Expires: Tue, 18 Jan 2022 10:05:09 GMTCache-Control: max-age=60复制代码备注抱着引用一手权威资料的想法,扒了《HTTP权威指南》,但读感着实差强人意。老手倡导《图解HTTP》起手,要敌对很多。参考资料 ...

March 18, 2022 · 2 min · jiezi

关于node.js:nvm安装使用以及遇到的坑

1、为什么应用nvm? 因为在不同的我的项目中,所应用的node版本可能不一样,所以装置nvm能够装置多个node版本,这样在不同我的项目中应用不同的node。2、nvm下载地址:https://github.com/coreybutle... 当初曾经更新到1.1.9版本了, 文件介绍: * nvm-noinstall.zip: 这个是绿色免装置版本,然而应用之前须要配置* nvm-setup.zip:这是一个安装包,下载之后点击装置,无需配置就能够应用,不便。* Source code(zip):zip压缩的源码* Sourc code(tar.gz):tar.gz的源码,个别用于*nix零碎3、装置流程: 这里以nvm-setup.zip装置为准,介绍装置流程: (1)装置nvm目录: (2)装置node.js目录 如果之前有装置nodejs,这块的目录就是nodejs的装置目录,如果之前没有装置,则这块的目录能够本人定义,然而最好和nvm放在一起,并且保障目录中没有空格。 装置实现之后,在命令行输出 nvm -v 查看装置版本,显示nvm信息则示意装置胜利。 4、应用 nvm -v: 查看nvm版本 nvm install 版本号: 装置node版本 nvm list: 查看曾经装置的node版本 nvm use 版本号: 切换node版本 nvm uninstall 版本号:卸载指定版本号的node npm install -g cnpm --registry=https://registry.npm.taobao.org //应用淘宝镜像5、遇到的坑 切换node版本时呈现乱码,上网搜了一圈,发现并没有卵用,只好本人钻研了下,发现cmd命令窗口须要用管理员身份关上能力切换。 这块的坑一个接一个,原本是想每次关上win+r默认为管理员身份关上,发现电脑是win10家庭版,没有本地安全策略,于是网上各种搜,终于找到解决办法。 依照以下内容执行,获取本地安全策略。https://jingyan.baidu.com/article/cdddd41cb0d76f53ca00e144.html本地安全策略设置,实现win+r实现以管理员身份关上。https://blog.csdn.net/qq_41968029/article/details/107336338还有一种办法是将家庭版转为专业版。http://www.xitongcheng.com/jiaocheng/xtazjc_article_42563.html

March 11, 2022 · 1 min · jiezi

关于node.js:推荐简单好用的终端输出彩色内容的开源nodejs工具库

在开发nodejs终端应用程序时,在终端输入带色彩的文本,反对以下个性: 反对按不同数据类型以不同的色彩显示,并且能够配置反对按DEBUG、INFO、WARN 、ERROR 、FATAL五个级别输入日志反对输入带色彩的模板字符串反对主动格式化显示{}和[]类型反对弱小的表格输入反对输入工作列表、进度条、横幅和树等扩大正确处理中文与英文混排时的对齐问题开源地址:https://gitee.com/zhangfisher/logsets.git 装置npm install logsetsyarn add logsetspnpm add logsets指南模板字符串输入对模板字符串进行插值后输入着色后的字符串。 import createLogger from "logsets"const logger = createLogger({...})logger.log("<模板字符串>",<变量1>,<变量1>,...,{end:"\n",append:" "})logger.log("<模板字符串>",<变量1>,<变量1>,...)logger.log("<模板字符串>",{<变量1>:<值>,<变量1>:<值>},)logger.log("<模板字符串>",{<变量1>:<值>,<变量1>:<值>},{end:"\n",append:" "})示例如下: import createLogger from "logsets"const logger = createLogger({...})// 命名插值变量logger.log("{a}+{b}={c}",{a:1,b:1,c:2})// 地位插值变量logger.log("My name is {}","tom")logger.log("{a}+{b}={c}",1,1,2)输入成果如下: 默认状况下,每次执行log办法实现后均会导致换行输入。log办法还反对配置输入参数: for(let i =0 ; i<=100; i++){ logger.log("正在下载:{}",i,{end:"\r"}) // 每行输入时最初打印\r回车符,回到行头,从而能够实现下载进度的更新。}logger.log() // 换行配置参数当log的参数大于=2个并且最初一个参数是{}时,将最初一个参数视为是输入配置参数。 { end:"\n", // 行完结字符,默认是换行会导致打印下一行,如\r则不会换行而只是回到行首 append:" " // 每个输入参数主动追加的字符,默认是一个空格}按数据类型输入提供print办法,用来间断输入多个通过着色的参数。 print(arg1,arg2,arg3,.....) print(arg1,arg2,arg3,.....,{end:"\n",append:" "}) // 减少可选的输入参数输入配置参数: 同log办法. 示例 import createLogger from "logsets"const log = createLogger({...})logger.print("String",true,100,()=>{},[1,2,3])logger.print(null,undefined)logger.print(/^colored$/g)logger.print(new Error("Value Error"))logger.print(new Date()) logger.print(class A{})logger.print(new (class X{})())logger.print({name:"tom",age:100,admin:true,posts:["a","b"],values:[1,2,3]},()=>"hello")输入成果如下: ...

March 11, 2022 · 5 min · jiezi

关于node.js:实现一个xx公司的仓储管理系统记录下全栈开发过程中的一些步骤及心得

技术选型前端:react + antd 后盾:express + mysql2 + log4js(日志服务,按业务模块记录) 部署:某讯的云服务器+域名,nginx代理前端、后盾服务 前端(治理端)应用脚手架创立我的项目,而后减少antd组件库页面鉴权左侧导航菜单:依据以后账号所属角色对应的菜单权限去生成路由/子路由设计我的项目代码目录设计 后端1、路由设计,依据业务辨别多个路由模块2、接口日志记录、鉴权(登录时写入cookie)3、登录时,明码做双层md5加密校验(内置超级管理员角色账号,超级管理员角色配置用户治理及角色治理菜单权限)4、实现文件上传5、明确业务及性能需要登录/退出菜单权限管制用户治理(超级管理员)角色治理(超级管理员)商品分类管理(层级关联抉择,暂反对2级)商品治理供应商信息管理6、数据库 - 表结构设计用户表(users)字段含意数据类型是否必传id用户idint1username用户名varchar(32)1password明码varchar(32) phone手机char(11) email邮箱varchar(32) role_id角色idINT1create_time创立工夫datetime1change_time最近批改工夫datetime1角色表(roles)字段含意数据类型是否必传id角色idint1name角色名称varchar(32)1auth_id授权人idint auth_name授权人varchar(32) auth_time受权工夫datetime create_time创立工夫datetime1menus有权限操作的菜单path的数组['/a','/b'] VARCHAR(200) default '/home' 商品分类表(categorys)字段含意数据类型是否必传id分类idINT1name分类名称varchar(64)1parentId父级分类idINT default null description分类简介varchar(500)1create_time创立工夫datetime1change_time最近批改工夫datetime1imgs图片['/a','/b'] VARCHAR(200) default '' 商品信息表(products)字段含意数据类型是否必传id商品idint1name商品名称varchar(64)1model规格型号varchar(64) description商品形容(详情)varchar(500) create_time创立此商品的工夫datetime1change_time最近批改工夫datetime1imgs图片['/a','/b'] VARCHAR(200) default '' categoryId所属分类的父分类idint1p_categoryId所属分类的idint1suppliers关联供应商(可能多个、搞个列表多选性能)[id,id2,id3...] VARCHAR(150) unit商品单位varchar(16) purchase_price进价double(精度低)、decimal(精度高) decimal(10,3) default 0.000 wholesale_price批发价double(精度低)、decimal(精度高)decimal(10,3) default 0.000 retail_price零售价double(精度低)、decimal(精度高)decimal(10,3) default 0.000 inventory_count累计入库数量 (默认0)int1show_count展厅寄存数量 (默认0)int delivery_count累计出库数量 (默认0)int current_count库存(以后理论库存数量)(默认0)int1effect用处varchar(500) remark备注varchar(500) status商品状态: 1:上架中, 2: 下架了tinyint(1) 这里的1示意的是最小显示宽度是1个字符;tinyint(2) 这里的2示意的是最小显示宽度是2字符 供应商信息表(suppliers)字段含意数据类型是否必传id供应商idint1name供应商姓名varchar(32)1address地址varchar(64) phone手机号char(11)1email邮箱varchar(32) goods供给物品varchar(500) goods_id供给物品idvarchar(150)预留字段:可能会去关联对应的多个商品id6、我的项目代码目录设计 ...

March 8, 2022 · 1 min · jiezi

关于node.js:nodejs学习之使用nodejs实现rmcpmv命令

闲来无事,本着学习nodejs的心态写点小东西,应用nodejs的api实现rm、cp和mv简略的删除/复制/挪动文件/文件夹。 rm删除文件其实也很简略,如果是文件就间接用fs.unlinkSync删除,如果是文件夹就递归一个个删除。 const fs = require("fs");const { join } = require("path");module.exports = async function deleteFiles(path) { // 判断一下门路是否实在存在 if (!fs.existsSync(path)) { console.warn(new Error("门路不存在。")); return; } const file = fs.lstatSync(path); // 是文件,间接删除 if (file.isFile()) { fs.unlinkSync(path); return; } // 是文件夹,遍历上面的所有文件 if (file.isDirectory()) { const files = await fs.readdirSync(path); if (files && files.length) { for (const fileName of files) { // 因为我之前我的项目应用的时候不想删除暗藏文件,所以在此过滤了.结尾的文件 if (fileName.startsWith(".")) { continue; } const p = join(path, fileName); const f = fs.lstatSync(p); // 是文件,间接删除 if (f.isFile()) { fs.unlinkSync(p); } // 是文件夹,递归调用 deleteFiles if (f.isDirectory()) { await deleteFiles(p); // 文件夹外部文件删除实现之后,删除文件夹 fs.rmdirSync(p); } } } return; }};Ïcp复制文件复制文件略微比删除复制一点,须要判断oldPath是文件还是文件夹,newPath是文件还是文件夹,再对不同的状况来生成可用的门路。 ...

March 4, 2022 · 2 min · jiezi

关于node.js:Docker-系列-03-入门-Node-服务

本篇文档对应的代码:https://github.com/LiangJunro...Docker 系列文档:https://github.com/LiangJunro...一、前文回顾通过前文的解说,想必小伙伴们对 Docker 的一些相干词语有所理解,这里咱们小小回归一下: 宿主机:你的电脑对应的零碎机子Dockfile:一份文件,能够用来创立镜像镜像:相似光盘,能够用来创立容器,相当于装置操作系统时须要用到的 ISO 文件容器:轻量级虚构技术,相当于通过 IOS 文件发明的一个零碎一千个哈姆雷特,每个人认识不同,欢送吐槽二、一个 Node.js Demo那么,既然要将 Node.js 塞到 Docker 上,咱们就要有一个 Node 服务,所以 jsliang 拿了本人写的一个根底 Node.js + TypeScript 的服务。 它的目录构造如下: docker-node> src.eslintrc.js.gitignorepackage-lock.jsonpackage.jsonREADME.mdtsconfig.json启动这个 Demo 只须要 2 步: 安装包:npm i启动服务:npm run robot等到每分钟的第 0 秒的时候,终端会打印: 这个 Demo 简略来说,就是通过 commander.js,运行 npm run robot 时,走命令 ts-node ./src/index.ts robot。 而后 /src/index.ts 中的工作,次要是: // ……代码省略console.log('你好,已进入程序'); // 打印schedule.scheduleJob('0 * * * * *', () => { // 设置定时工作 const { year, month, day, hour, minute, second } = getDateDetail(new Date()); console.log(`${year}/${month}/${day} ${hour}:${minute}:${second}`);});// ……代码省略即打印一行文本,而后在每分钟的第 0 秒打印 年/月/日 时:分:秒。 ...

March 4, 2022 · 2 min · jiezi

关于node.js:Nodejs中小数计算溢出问题以及如何解决

翻译平台有一个类似度检测的性能,其中有一个计算两个字符串类似度的函数后果发现两个齐全截然不同的字符串返回的类似度居然为 ,依据 余弦类似度算法[1] 失去 ,小于用户传递的最小类似度阈值1,因而归到了低类似度的文本中了。为什么会这样: 因为计算机执行的是二进制,并且js中数字都是浮点数示意的,并且规定了是 IEEE754的规范的双精度浮点数。 IEEE 754 规定了两种根本浮点格局:单精度和双精度。 单精度格局:具备24 位有效数字精度(蕴含符号),并总共占用32 位。 双精度格局:具备53 位有效数字精度(蕴含符号),并总共占用64 位。 再次深刻一下: 咱们应用 0.1 + 0.2进行推算 0.1转换为二进制 => 0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1100 ... 0.2转换为二进制 => 0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 ... 相加 => 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 ...

March 3, 2022 · 1 min · jiezi

关于node.js:Nodejs-Etimeout解决方案

在压测朋友圈服务的时候,因为接入了易盾的敏感词检测是http的申请,在TPS数百的时候,服务外部大量报错了 ETIMEOUT 的谬误; 在Node.js中能够在程序的入口文件相似 server.ts | app.ts 或者 入口文件 中 插入以下代码: process.env.UV_THREADPOOL_SIZE = '128' 但能够在启动时通过将UV_THREADPOOL_SIZE环境变量设置为任何值来更改它 (最大值为 1024)。 Node.js默认该值为4。 因为在DNS解析须要花大量工夫的,导致了阻塞,这个时候会返回etimeout的谬误。 在设置 UV_THREADPOOL_SIZE 属性之前 ,有近1%的申请是因为etimeout返回了http code 为 500的谬误。 设置之后: 该问题失去了解决。 参考资料: https://stackoverflow.com/que...

March 3, 2022 · 1 min · jiezi

关于node.js:websocket中Nodejs中的应用

简介WebSocket 协定在2008年诞生,2011年成为国际标准。所有浏览器都曾经反对了。 它的最大特点就是,服务器能够被动向客户端推送信息,客户端也能够被动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。 其余特点包含: (1)建设在 TCP 协定之上,服务器端的实现比拟容易。 (2)与 HTTP 协定有着良好的兼容性。默认端口也是80和443,并且握手阶段采纳 HTTP 协定,因而握手时不容易屏蔽,能通过各种 HTTP 代理服务器。 (3)数据格式比拟轻量,性能开销小,通信高效。 (4)能够发送文本,也能够发送二进制数据。 (5)没有同源限度,客户端能够与任意服务器通信。 (6)协定标识符是ws(如果加密,则为wss),服务器网址就是 URL。 readyStateConstantValueDescriptionCONNECTING0The connection is not yet open.OPEN1The connection is open and ready to communicate.CLOSING2The connection is in the process of closing.CLOSED3The connection is closed.坑点: websocket.readyState ===3 这里 没有走 close 的生命周期断线重连解决方案在websocket/ws 这个框架中,会有open,message,close 和 error生命周期。能够在 close 的生命周期中,执行reconnect流程参考最高赞答案.而后在error的生命周期中 打印crash日志,因为 error 必然触发close 所以只须要在 close 生命周期中进行 reconnect办法。 ws.on("close", function close() { console.log("ai connect close"); reconnect(); /// 每隔5s 重连 });ws.on("error", function error(error) { console.log("ai connect error", error); errorLogger.error("ai connect error", error); //打印crash日志 ws.close()});readyState=3 不会触发close的生命周期,所以须要对其独自解决,一旦检测到 其为3,则 terminate()该websocket.当然还有一种解决方案,因为在websocket中有心跳包的存在,详见How to detect and close broken connections?,能够在接管到来自其余socketServer的'pong'的信号,则写一个定时器,如果规定工夫内,没有收到来自下一个的心跳包则 terminate 该socket ...

March 3, 2022 · 1 min · jiezi

关于node.js:关于requiremkdirp创建文件夹

mkdirpnpm i mkdirp -S // 1.0.4明天在写上传文件时候,查看同步创立文件如是应用了mkdirp包,不过发现网络有大部分谬误用法,起因是mkdirp的版本升级了更改了用法网络谬误用法const mkdirp = require('mkdirp');await mkdirp(dir) //谬误用法一const mkdirp = require('mkdirp');//谬误用法二mkdirp('./tmp/foo/bar/baz', function (err) { console.log(err); });正确写法const mkdirp = require('mkdirp')// 返回值是一个Promise,解析为创立的一个目录 mkdirp('/tmp/foo/bar/baz').then(made => console.log(made))const mkdirp = require('mkdirp')// 返回目录 同步写法const made = mkdirp.sync('/tmp/foo/bar/baz')console.log(made)应用实例// 上传图片async uploadImg() { const { ctx } = this const parts = ctx.multipart({ autoFields: true }) const urls = [] const dir = path.join(this.config.baseDir, 'app/public/upload/image/', dayjs().format('YYYY-MM-DD')) await mkdirp.sync(dir) let stream while ((stream = await parts()) != null) { const fileType = stream.mimeType.split('/')[1] const filename = dayjs().valueOf() + '.' + fileType || stream.filename.toLowerCase() const target = path.join(dir, filename) urls.push(`/public/upload/image/${filename}`) const writeStream = await fs.createWriteStream(target) await pump(stream, writeStream) } return urls[0] }// 上传文件 async uploadFile() { const { ctx } = this const urls = [] const stream = await ctx.getFileStream() const dir = path.join(this.config.baseDir, 'app/public/upload/file/', dayjs().format('YYYY-MM-DD')) await mkdirp.sync(dir) const fileType = stream.filename.toLowerCase().split('.') const filename = dayjs().valueOf() + '.' + fileType[fileType.length - 1] // 生成写入门路 const target = path.join(dir, filename) const writeStream = await fs.createWriteStream(target) // 写入流 stream.pipe(writeStream) // 以管道形式写入流 await new Promise((resolve, reject) => { writeStream.on('finish', () => { // 监听写入实现事件 urls.push(`/public/upload/file/${filename}`) resolve(stream.fields) }) writeStream.on('error', async (err) => { await sendToWormhole(stream) // 敞开管道 writeStream.destroy() // 销毁 reject(err) }) }) return urls[0] }在线代码GitHub代码 ...

March 2, 2022 · 1 min · jiezi

关于node.js:基于nodejs的minio的sdk自建服务中转文件的断点续传方案

背景公司业务问题,就不过多论述,总的需要就是须要一个断点续传的性能公司的文件存储是应用的amazon s3,这个是通用的文件存储,相似阿里云的oss,一个文件能够当成是一个对象,能够给文件对象做一些操作,amazon s3是一个服务,能够创立一个一个桶用于存储文件,对于某个桶,有三种级别的权限:1、私有读,私有写;2、私有读,公有写;3、公有读,公有写为什么这个性能须要前端来做?因为后端只提供数据接口,不提供web服务,web服务都是前端本人开发和解决如果你不理解amazon s3或者阿里云的oss,那可能文章看的会有艰难简略文件上传amazon的s3,文件间接上传的话有这几种计划,分为:前端间接上传和应用sdk上传 一、前端间接上传,分私有写和公有写 私有写:能够间接拼接url:http://\<address\>/\<bucketname\>/\<objectname\>,在前端间接将文件发动put申请这个url即可,其中address是服务提供的域名,bucketname是咱们的桶名称,objectname是对象名(即文件名) 公有写:必须要用到minio的sdk,应用sdk提供的presignedPutObject办法生成一个上传地址,前端拿到链接后,也是在前端间接发动put申请即可,要留神,sdk只能运行在服务端,也就是必须要有本人的服务 二、应用sdk上传,sdk只能运行在服务端,流程基本上是,前端上传文件到服务端,服务端应用sdk将文件上传到S3的文件服务上 这两种计划,除了私有写的状况,其余的都须要有自建的服务端,而且从平安的角度上来说,设置私有写是不合理的 断点续传方案设计要做这个断点续传的性能,是必须要有本人的服务的,和大多数人一样,做这个断点续传的性能的时候,我也是去网上搜他人的做法,而后找到适合的办法后,联合咱们的我的项目,我设计了这样一个计划: 用户抉择文件后,前端应用file.slice对文件进行分片计算文件hash,也就是文件的md5,只有文件内容不变,文件的hash是不会变的,计算hash是一个同步工作,文件太大的话会把浏览器卡住,我应用的是spark-md5+浏览器的requestIdleCallback的api来解决的,能够依据本人我的项目的状况应用webworker也是能够的应用hash查问是否已有对应的文件,这个能够本人有本人的数据库,存储hash对应的文件链接,如果是用hash作为文件名的话,也能够调用minio的sdk的statObject办法晓得这个文件是否已上传,如果曾经有了文件信息,就能够不必上传文件,间接拿到链接即可,这个就是秒传的性能如果未上传,则读取服务器本地,以这个hash命名的文件夹下曾经上传了哪些分片,将已上传的分片返回给前端,前端选择性的上传未上传的分片即可,这个就是断点续传的性能前端上传分片的时候,会将文件的hash、第几个分片等这些信息作为参数给到服务端,服务端拿到文件后,会以hash命名文件夹,以第几个分片命名该分片,将分片存储在服务端所有分片上传实现后,在服务端对文件进行合并,再调用minio的putObject办法将文件上传到S3文件服务器,上传实现后,将服务器本地的文件删除整个断点续传性能是实现了,不过这个计划有个不完满的中央,就是分片文件要在服务端存储和合并,合并后才上传到文件服务上,据我所知,规范的S3自身是有断点续传和合并文件的性能的,可不可以间接上传分片的时候,将分片上传到S3文件服务器上,分片都上传实现后,间接在S3文件服务器合并文件?答案在前面,不过过后的确没有找到能够用的计划,惟一找到最靠近的计划是百度的智能云提供的api:https://cloud.baidu.com/doc/B... 然而minio的sdk不提供uploadPart办法,这个办法也行不通,所以只能先作罢 问题下面的计划有一个致命的问题没有思考到,就是线上是有多台机器的,这些分片会上传到不同的机器,合并文件的时候是没法合并的,导致下面设计的计划都不能用了,发现这个问题还是因为在解决一个合并文件的时候发现有分片未找到的问题的时候才思考到的,所以要重新考虑新的计划,着重点还是上传的分片怎么间接上传到S3文件服务器上,在S3文件服务器上合并 为了解决这个计划,我看了minio的源码,看了putObject的源码后,理解到putObject的外围流程如下: 应用block-stream2将文件进行分块应用objectName调用findUploadId查问uploadId,如果没有uploadId,会调用initiateNewMultipartUpload初始化一个uploadId,通过本人的一些测试能够失去一些信息: 2.1 每次调用initiateNewMultipartUpload返回的uploadId都不一样 2.2 findUploadId会返回最新的uploadId 2.3 通过查找别的信息得悉uploadId有7天的有效期 调用listParts取得已上传的part组合参数,调用makeRequest上传分片调用completeMultipartUpload实现分片上传,这个办法会将所有分片合并,并返回合并后的文件etag新计划通过看putObject办法的源码,咱们把咱们现有的计划做一些批改 用户抉择文件后,对文件进行分片计算文件hash,和之前统一,以文件hash作为新的文件名,或者加上固定的前缀,必须以固定的规定命名,同一个文件最好不要名字不统一,因为minio的服务端名字是惟一的key用文件名检索是否已存在文件,次要是调用的minio的statObject办法,如果未存在,以文件名获取uploadId,再用uploadId获取已上传的分片(此处区别于之前,因为分片文件不存在服务器本地,所以分片信息要存入数据库,其实还能够调用sdk的listParts办法获取到已上传的分片,然而调用listParts返回的信息没有带上冀望失去的partNumber参数,可能是公司搭建的S3服务的起因,所以分片只能入库)前端拿到已上传信息后,和之前解决统一,如果已存在文件,则不上传,否则计算须要上传分片而后上传自行开发一个uploadPart的办法,服务端接管到分片后,拿到分片文件的ArrayBuffer,拿到uploadId,拼装参数,调用sdk的makeRequest办法将分片上传到S3文件服务器服务器,上传实现后删除文件分片,将上传的分片信息入库前端承受到所有分片都上传实现后,调用合并文件接口,服务端合并文件,调用sdk的completeMultipartUpload办法,会将在S3文件服务器服务器上的分片都合并到此新的计划就实现了,上面贴上一些代码 前端: 文件分片: function createChunks(file, size = SINGLECHUNKSIZE) { let cur = 0, index = 1; const chunks = []; while (cur < file.size) { chunks.push({ start: cur, // 文件开始地位的字节 file: file.slice(cur, cur + size), // 分片文件 hash: "", // 文件hash progress: 0, // 上传进度 uploaded: false, // 是否已上传 index: index, // 第几个分片 }); index++; cur += size; } return chunks;}计算文件hash: ...

March 1, 2022 · 2 min · jiezi

关于node.js:unable-to-resolve-dependency-tree解决

我的起因是npm版本太高,以后是8 先一级一级切换,查看所有版本的命令是 npm show npm@* version 最初我发现6版本能够用,肯定要 -g npm install -g npm@6.14.16 最初解决了问题 给了三个新我的项目装了一天半,还是太菜了。

March 1, 2022 · 1 min · jiezi

关于node.js:Node的内存控制

Node的内存管制Allocation failed — process out of memory如果您看到下面的谬误,这意味着您的 NodeJS 应用程序内存不足,它耗费的内存超过了调配的内存,最终导致它自行终止。 当应用程序批处理大量数据时,数据处理算法的编写形式使其须要保留堆空间中的对象,直到解决实现。随着解决的进行,应用程序逐步应用了更多内存,V8也将 将破费更多工夫进行垃圾收集以开释未应用的内存,直到最终达到调配给过程的限度并导致了OOM。 Node.js 运行时在内存使的用方面十分高效,因而程序通常应用默认限度运行良好。并且,如果没有被动设置最大堆大小,程序则会应用默认内存限度,并且此默认值也是会依据 Node.js 版本和程序运行的零碎架构而有所不同。 上面咱们具体理解一下: 1.1 V8的垃圾回收机制与内存限度JavaScript与Java一样,由垃圾回收机制来进行主动的内存治理。对于性能敏感的服务器端程序,内存治理的好坏、垃圾回收情况是否低劣,都会对服务形成影响。而在Node中,这所有与V8引擎非亲非故。 1.2 V8的内存限度网上大都说,Node中通过JavaScript只能应用局部内存(64位约1.4G,32位约0.7G)。V8对内存做了限度。因而这种限度下,将会导致Node无奈间接操作大内存对象。然而随着版本升级,这个数据如同不是那么相对。 对于限度官网也没间接阐明(次要不确定是否能通过buffer.constants.MAX_LENGTH间接类比),所以写个小程序大略在64位零碎上跑一下。 Node.js (64位实测)版本限度 表头表头16.x4.0 GB15.x4.0 GB14.x4.0 GB13 .x2.0 GB12.x2.0 GB11.x1.4 GB10.x1.4 GB9.x1.4 GB官网文档buffer.constants.MAX_LENGTH 16.x12.x 11.x1.3 解决内存不足谬误为了解决 OOM 谬误,您须要做的就是显式配置内存限度应用 Node.js 命令行选项 -max-old-space-size=<size_megabytes>Javascript: node --max-old-space-size=2048 index.js #increase to 2GBnode --max-old-space-size=3072 index.js #increase to 3GBnode --max-old-space-size=4096 index.js #increase to 4GBnode --max-old-space-size=5120 index.js #increase to 5GBnode --max-old-space-size=6144 index.js #increase to 6GBnode --max-old-space-size=7168 index.js #increase to 7GBnode --max-old-space-size=8192 index.js #increase to 8GBTypescript的ts-node: ...

February 28, 2022 · 1 min · jiezi

关于node.js:告诉你Nodejs的fs模块扫描文件夹什么时候结束了

原文见我的公众号文章 优雅的让你晓得Node.js的fs模块扫描目录何时完结了需要提交软件著作权申请须要的软件源代码一份。 问题剖析读取我的项目目录,过滤某些文件夹(如:.git,.vscode等),只提取指定类型的文件的内容(如:js,wxml,wxss)。即把某我的项目下指定类型的代码提取进去,写入到同一个文件中。 封装满足以下特点的工具函数:可主动扫描指定门路下的所有文件及文件夹提供指定过滤(不扫描)某些文件夹的参数 ignoreDirs提供指定须要的文件类型的参数 allowExts提供读取到文件的监听事件 onFile提供读取门路失败的监听事件 onError提供当指定门路下无可扫描文件(扫描完结)的监听事件,办法外部扫描过程是同步执行的 onComplete函数自身只提供指定目录扫码工作,不含文件自身的读写操作先上代码/** * [printDirSync 同步遍历指定文件夹下的所有文件(夹),反对遍历完结回调 onComplete] * @param {*} dirPath * @param {*} options { allowExts: [], //指定须要的文件类型的门路,不指定则默认容许所有类型(不同于文件夹,文件类型太多,用疏忽的形式太麻烦,所以用了容许) ignoreDirs: [],//指定不须要读取的文件门路,不指定则默认读取所有文件夹 onFile: (fileDir, ext, stats) => {}, onError: (fileDir, err) => {}, onComplete: (fileNum) => {}, } */function printDirSync( dirPath, options = { allowExts: [], ignoreDirs: [], onFile: (fileDir, ext, stats) => {}, onError: (fileDir, err) => {}, onComplete: (filePaths) => {}, }) { const { allowExts, ignoreDirs, onFile, onComplete, onError } = options; let onPrintingNum = 0; //记录正在遍历的文件夹数量,用来判断是否所有文件遍历完结 let findFiles = []; //统计所有文件,在onComplete中返回 // 因为fs.stat是异步办法,通过回调的形式返回后果,不可控的执行程序影响是【否遍历完结】的判断 // 所以这里返回promise,配合sync/await模仿同步执行 const stat = (path) => { return new Promise((resolve, reject) => { fs.stat(path, function (err, stats) { if (err) { console.warn("获取文件stats失败"); if (onError && typeof onError == "function") { onError(path, err); } } else { if (stats.isFile()) { const names = path.split("."); const ext = names[names.length - 1]; // 对文件的解决回调,可通过allowExts数组过滤指定须要的文件类型的门路,不指定则默认容许所有类型 if ( !allowExts || allowExts.length == 0 || (allowExts.length && allowExts.includes(ext)) ) { if (onFile && typeof onFile == "function") { findFiles.push(path); onFile(path, ext, stats); } } } // 这里是对文件夹的回调,可通过ignoreDirs数组过滤不想遍历的文件夹门路 if (stats.isDirectory()) { if ( !ignoreDirs || ignoreDirs.length == 0 || (ignoreDirs.length && !ignoreDirs.includes(path)) ) { print(path); //递归遍历 } } } resolve(path + " stat完结"); }); }); }; // 解决正在遍历的文件夹遍历完结的逻辑:onPrintingNum-1 且 判断整体遍历是否完结 const handleOnPrintingDirDone = () => { if (--onPrintingNum == 0) { if (onComplete && typeof onComplete == "function") { onComplete(findFiles); } } }; // 遍历门路,记录正在遍历门路的数量 const print = async (filePath) => { onPrintingNum++; //进入到这里,阐明以后至多有一个正在遍历的文件夹,因而 onPrintingNum+1 let files = fs.readdirSync(filePath); //同步读取filePath的内容 let fileLen = files.length; // 如果是空文件夹,不须要遍历,也阐明以后正在遍历的文件夹完结了,onPrintingNum-1 if (fileLen == 0) { handleOnPrintingDirDone(); } //遍历目录下的所有文件 for (let index = 0; index < fileLen; index++) { let file = files[index]; let fileDir = path.join(filePath, file); //获取以后文件绝对路径 try { await stat(fileDir); //同步执行门路信息的判断 // 当该文件夹下所有文件(门路)都遍历结束,也阐明以后正在遍历的文件夹完结了,onPrintingNum-1 if (index == fileLen - 1) { handleOnPrintingDirDone(); } } catch (err) {} } }; print(dirPath);}再看咋用const { fs, printDir, printDirSync } = require("./file-tools");let dirPath = "/Users/yourprojectpath/yourprojectname";let allowExts = ["wxml", "wxss", "js", "txt", "md"];let ignoreDirs = [`${dirPath}/.git`, `${dirPath}/.DS_Store`, `${dirPath}/dist`];printDirSync(dirPath, { allowExts, ignoreDirs, onFile: (fileDir, ext, stats) => { let fileContent = fs.readFileSync(fileDir, "utf-8"); //同步读取文件内容 writeFile( `文件门路:${fileDir.replace("/Users/yourprojectpath/","")}\n${fileContent}\n\n`); }, onComplete: (files) => { console.log("疏忽的文件夹:", ignoreDirs); console.log("指定的文件类型:", allowExts); console.log( `门路 [${dirPath}] 遍历完结,发现 ${files.length}个 文件如下\n`, files ); },});function writeFile(data = "") { let outDir = "./dist/codes.txt"; fs.appendFileSync(outDir, data, { encoding: "utf8", });}最初我解释扫描指定门路下所有文件的根本流程 ...

February 25, 2022 · 3 min · jiezi

关于node.js:使用grunt脚本创建新分支

应用grunt 写一个创立新分支的task首选装置必要的润饰库npm i ora inquirer chalk --save编写task这一步次要为了给用户展现最近的几个分支用来判断新建是否反复,如果不必也能够,那就在拉取的时候通过shell判断下输出的分支号是否存在,不存在提醒就行 function getBranchCurrent(callback) { exec('git branch -a', function (err, stdout, stderr, cb) { const branchList = stdout.split('\n') const branchCurrentList = [] branchList.map(v => { const trimBranch = trim(v) if (trimBranch.includes('remotes')) { branchCurrentList.push(trimBranch) } }) callback(branchCurrentList.slice(branchCurrentList.length - 3)) });}// 创立最新分支 grunt.registerTask('creatBranch', '创立新的分支', function (type) { grunt.log.writeln('创立新branh-start'.green); var done = this.async(); var currentBranch = '' getBranchCurrent((versionList) => { grunt.log.writeln(('最近的3个近程分支' + versionList).blue); inquirer.prompt([ { type: 'input', name: 'newVersion', message: '请输出新的将要从master Check的分支号:', }, ]).then((answers) => { grunt.config.set('currentBranch', answers.newVersion); currentBranch = answers.newVersion inquirer.prompt([ { type: 'confirm', name: 'useNewVersion', message: '是否确认将此分支号: ' + answers.newVersion + '】 作为新的分支checkout到本地?', default: false }, ]).then((answers) => { if (answers.useNewVersion) { const spinner = ora('新分支 ' + currentBranch + '】 创立中。。。。。。').start() grunt.log.writeln(''); exec(`git checkout -b ${currentBranch} && git push --set-upstream origin ${currentBranch}`, function (err, stdout, stderr, cb) { if (err) { spinner.fail(); console.error(`创立失败: ${err}`); done() return; } done() spinner.succeed('祝贺,新分支创立胜利!'); }); } }) }) }) });

February 23, 2022 · 1 min · jiezi

关于node.js:使用nodejs为图片添加全页面半透明水印

业务背景作为中后盾我的项目的导出性能,通常会被要求具备导出的追溯能力。 当导出的数据状态为图片时,个别会为图片增加水印以达到此目标。 DEMO那么在导出图片前如何为其增加上能够作为导出者身份辨认的水印呢?先看成品: 上图原图为我轻易在网上找的一张图片,增加水印之后的成果如图所示。 业务需要合成这里咱们须要思考在此业务场景之下,这个需要的三个要点: 水印须要铺满整个图片水印文字成半透明状,保障原图的可读性水印文字应清晰可读选型如我一样负责在一个nodejs server上实现以上需要,可选项相当多,比方间接应用c lib imagemagick或者已有人封装的各种node watermarking库。在本文中,咱们将抉择应用对Jimp库的封装。 Jimp 库的官网github页面上这样形容它本人: An image processing library for Node written entirely in JavaScript, with zero native dependencies. 并且提供为数众多的操作图片的API blit - Blit an image onto another.blur - Quickly blur an image.color - Various color manipulation methods.contain - Contain an image within a height and width.cover - Scale the image so the given width and height keeping the aspect ratio.displace - Displaces the image based on a displacement mapdither - Apply a dither effect to an image.flip - Flip an image along it's x or y axis.gaussian - Hardcore blur.invert - Invert an images colorsmask - Mask one image with another.normalize - Normalize the colors in an imageprint - Print text onto an imageresize - Resize an image.rotate - Rotate an image.scale - Uniformly scales the image by a factor.在本文所述的业务场景中,咱们只需应用其中局部API即可。 ...

February 21, 2022 · 2 min · jiezi

关于node.js:Modbus的报文格式plc

网络上的modbus阐明都是 读放弃寄存器 之类很难懂的词汇,在这里做个简化阐明的笔记。modbus具体性能码及错误码参考 【其余】 局部的链接 plc 的寄存器分类: 开关量通道,用x、y示意,寄存器序号8进制计数,x0-x7,x10-x15为输出,只读。y0-y7,y10-y15为输入。内存变量记为m,寄存器序号十进制,比方m19。单变量长度为1位 模拟量通道,sd示意。内存模拟量记为d,寄存器序号十进制。单变量长度为2字节 罕用性能码 0x01: 读线圈寄存器---------- 批量读y0x02: 读离散输出寄存器---------- 批量读x0x03: 读放弃寄存器---------- 批量读d0x04: 读输出寄存器---------- 读输出模拟量通道sd(未测试)0x05: 写单个线圈寄存器---------- 写输入模拟量通道sd(未测试)0x06: 写单个放弃寄存器---------- 单个写d0x0f: 写多个线圈寄存器---------- 批量写输入模拟量通道sd(未测试)0x10: 写多个放弃寄存器---------- 批量写d详解: 0x01 批量读y 发送:站号1字节-0x01,性能码1字节-0x01,起始地址2字节-0x00 0x00,数据长度2字节-0x00 0x10,crc2字节 返回:站号1字节-0x01,性能码1字节-0x01,数据字节计数1字节-0x02,数据2字节-0x20 0x00,crc2字节解释:申请读y0起16个开关量状态,响应0x20 0x00,即y7-y0状态为0010 0000,y17-y10状态为0000 0000,只有y5是1(依据设施大小端不同留神程序) 0x02 批量读x同0x01 0x03 批量读d发送:站号1字节-0x01,性能码1字节-0x03,起始地址2字节-0x00 0x00,数据长度2字节-0x00 0x02,crc2字节 返回:站号1字节-0x01,性能码1字节-0x03,数据字节计数1字节-0x04,数据4字节-0x06 0xa4 0x0a 0x8c,crc2字节 解释:申请读d0起2个模拟量状态,响应0x06 0xa4 0x0a 0x8c,即d1为0x06 0xa4=1700,d2为2700 0x06 单个写d发送:站号1字节-0x01,性能码1字节-0x06,起始地址2字节-0x00 0x07,数据2字节-0x0a 0xa0,crc2字节 返回:同发送解释:申请写d7模拟量状态,响应雷同报文,写入 0x0a 0xa0 0x10 批量写d发送:站号1字节-0x01,性能码1字节-0x10,起始地址2字节-0x00 0x07,数据长度2字节-0x00 0x02,数据字节数1字节-0x04,数据4字节-0xab 0xcd 0x98 0x76,crc2字节 返回:站号1字节-0x01,性能码1字节-0x10,起始地址2字节-0x00 0x07,操作数据长度2字节-0x00 0x02,crc2字节 ...

February 18, 2022 · 1 min · jiezi

关于node.js:Nodejs-源码分析-加载-js-文件

title: Node.js 源码剖析 - 加载 js 文件date: 2018-11-30 21:04:49tags: - Node.js- Node.js 源码剖析- 源码剖析categories: - Node.js 源码剖析此文最后于四年前公布在集体站上的,现迁徙至此重发,原链接:https://laogen.site/nodejs/no...《Node.js 源码剖析》 系列目录页:https://laogen.site/nodejs/no...提出问题理解 js 文件加载前的筹备工作在《从 main 函数开始》这篇中说到了 LoadEnvironment() 函数负责加载 js 代码,但并没有持续阐明加载细节。 这篇从 LoadEnvironment() 开始探索 js 代码加载的具体过程。 <!-- more --> LoadEnvironment()LoadEnvironment() 的逻辑分两局部: 加载并执行两个 js 文件:loaders.js node.js,执行后失去两个启动函数;别离调用这两个启动函数:loaders_bootstrapper() 和 node_bootstrapper();这段代码比拟长,咱们把不影响主逻辑的代码省略掉,而后间接在代码中以正文的模式来解释: void LoadEnvironment(Environment* env) { // ... /************************************************************/ /**** 第一步.加载并执行两个 js 文件:`loaders.js` `node.js`****/ /************************************************************/ // The bootstrapper scripts are lib/internal/bootstrap/loaders.js and // lib/internal/bootstrap/node.js, each included as a static C string // defined in node_javascript.h, generated in node_javascript.cc by // node_js2c. // 这两个 js 文件在 node 构建过程中就被转换成了 C++ 代码,即以 C++ 字符串的 // 模式存在于 C++ 代码中,依据这个文件名就能够间接获取相应的 js 代码字符串; // loaders.js 的文件名 Local<String> loaders_name = FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/loaders.js"); // 执行 loaders.js 失去函数: `loaders_bootstrapper` MaybeLocal<Function> loaders_bootstrapper = GetBootstrapper(env, LoadersBootstrapperSource(env), loaders_name); // node.js 文件名 Local<String> node_name = FIXED_ONE_BYTE_STRING(env->isolate(), "internal/bootstrap/node.js"); // 执行 loaders.js 失去函数: `loaders_bootstrapper` MaybeLocal<Function> node_bootstrapper = GetBootstrapper(env, NodeBootstrapperSource(env), node_name); // 下面代码中:LoadersBootstrapperSource() & NodeBootstrapperSource() 是 // 在 /src/node_javascript.h 头文件中申明的,node 源码中并没有它们的具体实现, // 它们的实现代码是在 node 自身构建过程中生成的; // 至于 GetBootstrapper(),它的作用是编译&执行 js 代码,返回执行后果。 if (loaders_bootstrapper.IsEmpty() || node_bootstrapper.IsEmpty()) { return; } Local<Object> global = env->context()->Global(); // ... // Expose the global object as a property on itself // (Allows you to set stuff on `global` from anywhere in JavaScript.) global->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global); /*************************************************************************/ /* 第二步.别离调用这两个启动函数:loaders_bootstrapper、node_bootstrapper ****/ /*************************************************************************/ // Create binding loaders // 基于 GetBinding() 函数模板 创立 get_binding_fn 函数 Local<Function> get_binding_fn = env->NewFunctionTemplate(GetBinding)->GetFunction(env->context()) .ToLocalChecked(); // 基于 GetLinkedBinding() 函数模板 创立 get_linked_binding_fn 函数 Local<Function> get_linked_binding_fn = env->NewFunctionTemplate(GetLinkedBinding)->GetFunction(env->context()) .ToLocalChecked(); // 基于 GetInternalBinding() 函数模板 创立 get_internal_binding_fn 函数 Local<Function> get_internal_binding_fn = env->NewFunctionTemplate(GetInternalBinding)->GetFunction(env->context()) .ToLocalChecked(); // 下面三个函数会作为 调用 loaders_bootstrapper() 时的参数。 Local<Value> loaders_bootstrapper_args[] = { env->process_object(), get_binding_fn, get_linked_binding_fn, get_internal_binding_fn, Boolean::New(env->isolate(), env->options()->debug_options->break_node_first_line) }; // loaders_bootstrapper() 调用后果将保留在这个变量, // 接下来,它将被作为参数传给另一个启动函数:node_bootstrapper() Local<Value> bootstrapped_loaders; // 调用启动函数 loaders_bootstrapper() if (!ExecuteBootstrapper(env, loaders_bootstrapper.ToLocalChecked(), arraysize(loaders_bootstrapper_args), loaders_bootstrapper_args, &bootstrapped_loaders)) { return; } // Bootstrap Node.js Local<Object> bootstrapper = Object::New(env->isolate()); SetupBootstrapObject(env, bootstrapper); Local<Value> bootstrapped_node; Local<Value> node_bootstrapper_args[] = { env->process_object(), bootstrapper, bootstrapped_loaders }; // 调用启动函数 loaders_bootstrapper() if (!ExecuteBootstrapper(env, node_bootstrapper.ToLocalChecked(), arraysize(node_bootstrapper_args), node_bootstrapper_args, &bootstrapped_node)) { return; }}总结LoadEnvironment() 次要是调用了两个 启动函数(Bootstrapper) ...

February 18, 2022 · 2 min · jiezi

关于node.js:Nodejs-源码分析-原生模块C模块的注册

title: Node.js 源码剖析 - 原生模块(C++模块)的注册date: 2018-11-28 21:04:49tags: - Node.js- Node.js 源码剖析- 源码剖析categories: - Node.js 源码剖析此文最后于四年前公布在集体站上的,现迁徙至此重发,原链接:https://laogen.site/nodejs/no...《Node.js 源码剖析》 系列目录页:https://laogen.site/nodejs/no...上一篇提到 RegisterBuiltinModules() 注册了原生 C++ 模块没有具体开展,这里就从这个函数开展。 <!-- more --> 将 RegisterBuiltinModules() 层层开展/* src/node.cc:3066 */void RegisterBuiltinModules() {#define V(modname) _register_##modname(); NODE_BUILTIN_MODULES(V)#undef V}首先定义了一个宏 V 为 _register_##modname(), 能够看出 V 开展后是一个函数调用相似这样: _register_xx(); 随后,RegisterBuiltinModules() 理论是宏 NODE_BUILTIN_MODULES(V) 来实现的,咱们看看它的定义: /* src/node_internals.h:147 */#define NODE_BUILTIN_MODULES(V) \ NODE_BUILTIN_STANDARD_MODULES(V)// ...进一步查看 NODE_BUILTIN_STANDARD_MODULES(V) 的定义: /* src/node_internals.h:106 */#define NODE_BUILTIN_STANDARD_MODULES(V) \ V(async_wrap) \ V(buffer) \ V(cares_wrap) \ V(config) \ V(contextify) \ V(domain) \ V(fs) \ V(fs_event_wrap) \ V(heap_utils) \ V(http2) \ V(http_parser) \ V(inspector) \ V(js_stream) \ V(messaging) \ V(module_wrap) \ V(options) \ V(os) \ V(performance) \ V(pipe_wrap) \ V(process_wrap) \ V(serdes) \ V(signal_wrap) \ V(spawn_sync) \ V(stream_pipe) \ V(stream_wrap) \ V(string_decoder) \ V(symbols) \ V(tcp_wrap) \ V(timer_wrap) \ V(trace_events) \ V(tty_wrap) \ V(types) \ V(udp_wrap) \ V(url) \ V(util) \ V(uv) \ V(v8) \ V(worker) \ V(zlib)这个宏定义中屡次调用宏 V,还记得这个宏吗,在下面定义的:#define V(modname) _register_##modname();,那咱们把它开展后就是: ...

February 18, 2022 · 3 min · jiezi

关于node.js:Nodejs-源码分析-从-main-函数开始

title: Node.js 源码剖析 - 从 main 函数开始date: 2018-11-27 21:30:15tags: - Node.js- Node.js 源码剖析- 源码剖析categories: - Node.js 源码剖析此文最后于四年前公布在集体站上的,现迁徙至此重发,原链接: https://laogen.site/nodejs/no...《Node.js 源码剖析》 系列目录页:https://laogen.site/nodejs/no...小指标晓得程序大略执行逻辑,关键点执行的程序咱们平时在终端敲下 node app.js 后,产生了什么。 具体点,晓得 node.js 原生(C++)模块什么时候加载的,在哪加载的;晓得咱们的 js 代码是在哪个环节被加载执行的;晓得过程的主循环(事件循环)什么时候启动的; 有了这个小指标的根底,在接下来的文章中,咱们再进一步的摸索 node.js 原生模块的注册是怎么实现的,怎么获取 & 初始化的,怎么曝露给 js 环境调用的;再细说 node.js 的模块机制,咱们通常的 app.js 怎么被执行的; <!-- more --> 贴代码阐明限于篇幅,本文只先把大体执行流程捋进去,前面再开文一块块的捋。 原代码太长,先把不影响咱们剖析的无关代码去掉,贴上来无关整体执行逻辑的代码,代码中的 // ... 正文意思是这个中央有被省略的代码。 每段代码第一行的正文都会指出源文件地位,一些代码解说会在代码段中的正文中进行; 本文不再介绍 V8 和 Libuv 的常识,会开专门的分类写 V8 和 Libuv,参考 {% post_link nodejs/nodejs-src/index Node.js 源码剖析 - 前言 %} 开捋:从 main 函数到过程主循环main 函数/* src/node_main.cc:93 */int main(int argc, char* argv[]) { // ... return node::Start(argc, argv);}main函数 在 src/node_main.cc 这个文件中,这个文件次要就是寄存 main函数。 ...

February 18, 2022 · 4 min · jiezi

关于node.js:lafjs-开源的云开发框架READMEmd

laf.js 云开发框架在线文档:https://docs.lafyun.com/ 在线体验:https://www.lafyun.com/ 介绍laf.js 是一套开箱即用、残缺、开源、为开发者提供的基于 serverless 模式和 js 编程的云开发框架。 用相熟的 js,轻松搞定前后台整体业务,前端秒变全栈。 laf.js 让每个开发者都能够随时领有一个本人的云开发平台! 交换 QQ 群:603059673 lafyun.com 正式上线!可间接在线体验,立刻创立 laf 云开发应用服务! 开发者可收费在 lafyun.com 上疾速创立本人的利用,不必关怀服务器部署和运维工作,立刻领有利用独立域名及 HTTPS 证书,疾速上线利用! 开发者能够在公有服务器上部署一套 laf 云开发平台,可不便的将 lafyun.com 中的利用迁至本人的 laf 云开发平台中运行! 次要内容提供云函数引擎、文件存储、数据拜访策略、触发器、WebSocket 等能力,开箱即用,5 分钟上线利用,前端秒变全栈前端可应用 laf-client-sdk “直连”数据库,无需与服务端对接口另有 Flutter SDK less-api-client,疾速上线挪动端利用反对 h5、小程序、Uni-app、Flutter 等客户端环境应用提供云开发控制台,在线治理云函数、文件、数据库、近程部署、日志,在线编写、调试云函数,全智能提醒 IDE初心场景用于疾速开发 MVP,专一于客户端业务,极大水平缩小服务端开发工作量自建属于本人可控的云开发平台谁适宜应用 ?云开发用户如果你喜爱微信云开发的极速体验,但又不想局限于微信等具体平台的限度,那么能够基于 LaF 搭建属于本人的云开发平台; laf.js 也是以后已知的惟一的开源云开发平台,技术选型更自信、危险更可控、场景更易扩大自建云开发,能够获取极速的云开发体验,同时没有技术选型时迁徙平台的懊恼顾虑集体开发者、初创守业团队在产品初期基于 laf.js 能够极大缩小服务端 API 的数量; 依据咱们的实践经验,初期能节约 90% 的服务端 API; 专一于产品业务自身,疾速推出最小可用产品(MVP),疾速进行产品、市场验证。 软件开发商将无需雇佣 php 或 java 等服务器工程师,开发成本大幅降落; 开发效率大幅晋升、上线和迭代速度大幅提速; 可残缺交付整个云开发框架源码,私网部署; 运行截图利用列表 云函数列表 在线开发云函数 云存储:文件治理 ...

February 18, 2022 · 1 min · jiezi

关于node.js:node连接mysql

1.开发环境 vue+ node2.电脑系统 windows 10 专业版3.在开的开发的过程中,咱们总是会应用 一门后端语言 来操作数据库,我抉择的是 node,数据库是 mysql ,上面我简略的说一下,应用 node 怎么连贯 mysql 数据库,并把查问到的数据库的数据返回给前端。办法如下:4.在node 中接口中增加如下代码: 4.1 首先 要装置 在 node 中装置 mysql ,代码如下:npm install mysql --save 4.2 废话不多说,间接上操作: //新建 mysql 文件夹,mysql下新建index.js,代码如下const mysql=require(`mysql`);const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'chen', database: 'chen', port: '3306'});//创立一个connectionconnection.connect(function(err){ if(err){ console.log('连贯失败:'+err); return; } console.log('连贯胜利');});module.exports=connection;4-3.在对应的接口中应用 const connection=require('../mysql')router.post("/",function(req,res,next){ console.log(req.body); console.log("+++++++++++"); connection.query("select * from userTable where name='"+req.body.name+"'",(err,result)=>{ if(err){ console.log("查问失败了"+err); }else{ console.log(result); let data=undefined; if(result.length===0){ data={ code:200, msg:"申请胜利,暂无数据", data: result, } }else { data={ code:200, msg:"申请胜利,注册接口", data:result }; } res.json(data); } })})module.exports = router;4-4.扩大 ...

February 18, 2022 · 1 min · jiezi

关于node.js:你不知道的node安装方法

在开发的过程中,咱们常常会须要装置 node环境,在装置多边 node环境之后,我本人总结了一下,才发现装置 node原来环境原来能够这么简略,心愿对你有所帮忙。1.废话不多说,间接上操作 倡议抉择稳定版,点击 其余下载 滚动到最上面,点击 所有下载选项 依据本人电脑进行抉择下载实现之后,会失去有一个压缩包,进行解压,你会看到这样的成果 把这个解压文件,拷贝到你想要装置的地位,而后配置一下环境。2.做完下面的操作之后,须要执行如下命令: npm config set prefix "D:\SDE\node-v14.15.4-win-x64\node_global"npm config set cache "D:\SDE\node-v14.15.4-win-x64\node_cache"留神:D:\SDE\node-v14.15.4-win-x64\是我的项目目录,依据本人的状况,本人批改。3.增加到环境变量 把D:\SDE\node-v14.15.4-win-x64\node_global 增加到全局环境变量如果还不晓得如何增加环境变量,在这里一个解说,找到电脑,右击属性>高级零碎设置>环境变量,找到零碎变量(点击编辑,而后点击新增,把 D:\SDE\node-v14.15.4-win-x64\node_global 复制进去,保留就能够了)4.本期的分享到了这里就完结啦,是不是很nice,心愿对你有所帮忙,让咱们一起致力走向巅峰。

February 18, 2022 · 1 min · jiezi

关于node.js:Nodejs有哪些调试方法

一、Node有哪些调试工具咱们晓得客户端脚本能够在浏览器里调试,那么nodejs怎么调试呢? 这里次要讲2个调试办法,心愿能对大家有所帮忙: 1、Chrome浏览器调试nodejs 2、VSCode调试nodejs二、Chrome浏览器调试nodejs(ChromeDevTools 55+反对)1、运行脚本 1)、web服务利用: node –inspect app.js 或者 node –inspect-brk app.js 2)、非web服务利用: node --inspect-brk=9229 app.js PS:-brk指定第一行设置断点,一开始就是暂停状态, =9229指定调试端口为 9229,这是调试工具默认的通信端口2、chrome浏览器里关上:chrome://inspect/#devices,会显示如下页面(Target要等一会能力呈现)。 3、点击上图红框中的inspect按钮,即可进入程序调试界 调试工具次要有四个面板:Console:控制台、Sources:源码、Memory:内存、Profiler:性能。次要讲Sources面板,调试时面板从左到右能够看到CallStack、Breakpoints、Scope、Watch等折叠项。Scope双击Local的变量值可进入编辑状态。 4、除了chrome://inspect/#devices之外,输出http://127.0.0.1:9292而后关上开发者工具,点击node图标,也能够进入调试程序。 5、遗记写 –inspect 怎么办?(Linux零碎) 关上调试工具的前提是,启动 Node 脚本时就加上--inspect参数。如果忘了这个参数,还能不能调试呢?答复是能够的。首先,失常启动脚本。 1)、失常启动脚本:node app.js 2)、在另一个命令行窗口,查找下面脚本的过程号。 $ ps ax | grep app.js 30464 pts/11 Sl+ 0:00 node app.js 30541 pts/12 S+ 0:00 grep app.js3)、下面命令中,app.js的过程号是30464。接着运行上面命令: node -e'process._debugProcess(30464)'4)、下面命令会建设过程 30464 与调试工具的连贯,而后就能够关上调试工具了。 5)、还有一种办法,就是向脚本过程发送 SIGUSR1 信号,也能够建设调试连贯。(windows上不可用) $ kill -SIGUSR1 304646、怎么启用近程调试计划 如果须要近程调试生产代码,倡议不要让调试器监听公共IP地址,倡议应用ssh隧道来调试。怎么启用近程调试计划: 1)、近程机器上启动过程:node –inspect app.js 2)、在要启动调试客户端连贯的本地计算机上,能够设置ssh隧道: ...

February 18, 2022 · 1 min · jiezi

关于node.js:手写nodejs原生require方法

前言这两天在学习nodejs相干的货色,在b站上看到一个up主分享的视频还挺不错的,于是跟着敲了一下。 实现第一步:定义myRequire办法 function myRequire(filename) { // 获取绝对路径 const mPath = Module._resolveFilename(filename); // 缓存优先 const cacheModule = Module._cache[mPath]; if (cacheModule) return cacheModule.exports; // 创立空对象加载指标模块 const module = new Module(mPath); // 缓存已加载模块 Module._cache[mPath] = module; // 执行加载 module.load(); return module.exports;}第二步:定义Module类办法 function Module(id) { // 模块id理论就是绝对路径 this.id = id; this.exports = {};}第三步:实现Module._resolveFilename获取文件绝对路径的办法,只对以后的目录做了简略的查找、判断,理论会向上一层层查找模块,此处省略。当找不到时会尝试对文件名拼接文件后缀,此处只提供了js和json的办法,如果还是找不到便抛出谬误。 Module._resolveFilename = function (filename) { // 拼接当前目录和文件名 const mPath = path.join(__dirname, filename); // 判断此文件是否存在,存在之后返回 if (fs.existsSync(mPath)) { return mPath; } // 如果不存在,尝试拼接后缀 const suffixs = Object.keys(Module._extensions); for (let i = 0; i < suffixs.length; i++) { const _mPath = mPath + suffixs[i]; if (fs.existsSync(_mPath)) { return _mPath; } } // 找不到抛错 console.log(new Error(`${filename} is no exits`));};第四步:当获取到文件的绝对路径后,先去缓存中查找模块,如果有间接返回。反之创立模块对象,并向缓存中增加此模块,最初执行模块加载,也是外围的编译执行模块。 ...

February 17, 2022 · 1 min · jiezi

关于node.js:Nodejs中moduleexports-和exports使用误区

一、module,module.exports ,exports含意 module对象:在每个 .js 自定义模块中都有一个 module 对象,它外面存储了和以后模块无关的信息module.exports 对象:在node里自定义的模块中,能够应用 module.exports 对象,将自定义的模块内局部的成员共享进来被应用。当外界(其余js文件)用require() 办法导入自定义模块时,失去的就是 module.exports 所指向的对象exports对象:因为 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。默认状况下,exports 和 module.exports 指向同一个对象留神:应用 require() 办法导入模块时,导入的后果,永远以 module.exports 指向的对象为准换句话说最终共享的后果,还是以 module.exports 指向的对象为准 二.案例 通过案例来了解二者的关系 案例一: 定义代码 //文件名:01.module.exports和exports误区exports.name="小吴"module.exports ={    性别:"男",    age:18     输入代码 //文件名:01-test //为了测试module.exports ,exports指向后果 案例二三四的输入代码都是此js代码文件const obj=require("./01.module.exports和exports误区")console.log(obj); 输入后果 解释:因为默认状况下,exports 和 module.exports 指向同一个对象,所以开始二者都是指向一个空对象,当export指向新对象name="小吴"后,此时二者都指向这个对象,然而执行前面代码则是在内存中新开拓一个空间存储新对象 {性别:“男”,age:18} ,且把这个新对象的援用交给了module.exports,则module.exports就指向新的对象,不指向之前的空对象了,而且因为最终共享的后果,以module.exports 指向的对象为准,所以案例输入如上图所示 案例二 定义代码 module.exports.name="小吴"exports ={    性别:"男",    age:18     } 输入后果 解释:同理当module.exports指向对象name="小吴"后,执行前面代码,,exports指向新对象{性别:“男”,age:18},因为最终共享的后果,还是以 module.exports 指向的对象为准 所以案例输入如上图所示 案例三 定义代码 exports.name="小吴"module.exports.age=18 ...

February 16, 2022 · 1 min · jiezi

关于node.js:解析RSSHub文档自动生成API

前言我的项目正式版公布了,最近比拟安闲,晃荡的时候看到rsshub这个库,想玩一下,然而rsshub文档里的接口太多了,本人手敲又嫌麻烦,突发奇想解析rsshub的文档主动生成所有文档呈现的api给前端页面应用。 不是什么起因我的yarn和npm都装不了rsshub这个包,我是间接拉GitHub的rsshub下来用的,能装的能够间接装置,不行的也能够像我一样拉下来用,就是有点俊俏。 我的项目地址rsshub-demo 效果图没有特地去写款式,有局部接口有问题,可能获取不到数据 代码首先第一步也是最外围的一步就是解析文档,提取无效信息,当然是用正则去解析对应的api名称,题目,path等,我定义了一个常量先申明这些正则规定。 const RegMap = { Type: new RegExp(/\s#\s(.+)\s/g), Content: new RegExp( /\s##.+\s+###.+\s+(<Route.+>)|(<\/Route>\s+###.+\s+<Route.+>)/g ), Title: new RegExp(/\s##\s(.+)\s/g), ChildTitle: new RegExp(/\s###(.+)/g), Route: new RegExp(/(\<Route.+\>)/g), Example: new RegExp(/example="(\S+)"/g), Path: new RegExp(/path="(\S+)"/g), ParamsDesc: new RegExp(/paramsDesc="(.+)"/g),};解析文档内容,这里我是间接下载了文档的,你也能够去申请文档来解析,找无效信息的代码略微有点low,解析之后生成接口具体的题目、path等信息的json文件 let type; const data = await fs .readFileSync(join(__dirname, `../../docs/${file}`)) .toString(); data.replace(RegMap.Type, (_, val) => (type = val)); const list = data.match(RegMap.Content); if (!list) return; const result = []; for (let index = 0; index < list.length; index++) { const content = list[index]; let title, childTitle, route, example, path, paramsDesc; content.replace(RegMap.Title, (_, val) => (title = val)); content.replace(RegMap.ChildTitle, (_, val) => (childTitle = val)); content.replace(RegMap.Route, (_, val) => (route = val)); if (route) { route.replace(RegMap.Example, (_, val) => (example = val)); route.replace(RegMap.Path, (_, val) => (path = val)); route.replace(RegMap.ParamsDesc, (_, val) => (paramsDesc = val)); } if (title) { result.push({ title, children: [ { title: childTitle, example, path, paramsDesc, }, ], }); } else { const parent = getParent(result, index); if (parent) { parent.children.push({ title: childTitle, example, path, paramsDesc, }); } } } fs.writeFileSync(`./api/${file}.json`, JSON.stringify({ type, result }));读取生成的接口信息json文件。 ...

February 16, 2022 · 3 min · jiezi

关于node.js:NodeJS中的Crypto使用

NodeJS中的Crypto应用 在爬虫JS解密的时候常常会遇到常见的加密,例如:MD5,Sha1,Sha256,AES,RSA等加密算法,这些能够在Python中调用,当然有时候采纳NodeJS调用也很不便,相熟NodeJS常见的加密算法对逆向JS很有帮忙。NodeJS 中的 Crypto 模块提供了加密性能,包含对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证性能的一整套封装。 Hash 将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规定就是哈希算法,而通过原始数据映射之后失去的二进制值串就是哈希值(散列值).一个优良的哈希算法须要满足: 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法);对输出数据十分敏感,哪怕原始数据只批改了一个 Bit,最初失去的哈希值也大不相同;散列抵触的概率要很小,对于不同的原始数据,哈希值雷同的概率十分小;哈希算法的执行效率要尽量高效,针对较长的文本,也能疾速地计算出哈希值。哈希算法严格来说并不属于加密算法,传统意义上的 加密 是与 解密 相配对的。哈希算法只能加密不能反向解密。 MD5 在NodeJS中 MD5 Hash 函数的用法如下: const crypto = require('crypto'); const hash = crypto.createHash('md5');console.log(hash.update('666666').digest('hex'))// f379eaf3c831b04de153469d1bec345e const hash2 = crypto.Hash('md5');console.log(hash2.update('666666').digest('hex'))// f379eaf3c831b04de153469d1bec345e 其中摘要的编码方式有如下三种: latin1hexbase64 Sha1 const crypto = require('crypto');const hash = crypto.createHash('sha1');console.log(hash.update('666666').digest('hex'))// 1411678a0b9e25ee2f7c8b2f7ac92b6a74b3f9c5 const hash2 = crypto.Hash('sha1');console.log(hash2.update('666666').digest('hex'))// 1411678a0b9e25ee2f7c8b2f7ac92b6a74b3f9c5 Base64 百度百科中对Base64有一个很好的解释:“Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来示意二进制数据的办法”。什么是“可打印字符”呢?为什么要用它来传输8Bit字节码呢?在答复这两个问题之前咱们有必要来思考一下什么状况下须要应用到Base64?Base64个别用于在HTTP协定下传输二进制数据,因为HTTP协定是文本协定,所以在HTTP协定下传输二进制数据须要将二进制数据转换为字符数据。然而间接转换是不行的。因为网络传输只能传输可打印字符。什么是可打印字符?在ASCII码中规定,0~31、127这33个字符属于控制字符,32~126这95个字符属于可打印字符,也就是说网络传输只能传输这95个字符,不在这个范畴内的字符无奈传输。那么该怎么能力传输其余字符呢?其中一种形式就是应用Base64。 严格来说Base64也不是加密算法,然而爬虫中也会常常遇到,所以在此给出在NodeJS中的Base64的"加密"与"解密"。在浏览器中加密与解密别离对应 btoa 和 atob。 Base64加密 对应浏览器中的 btoa: const data = '666666';const encodedData = Buffer.from(data, 'utf-8').toString('base64'); // 输出编码为utf8,输入为base64console.log(encodedData);// NjY2NjY2 ...

February 15, 2022 · 2 min · jiezi

关于node.js:nodejs学习文档

Nodejs长处①运行在V8JavaScript引擎上(高性能)②事件驱动③非阻塞的IO模型④丰盛的生态圈(npm下载资源) Nodejs装置首先咱们能够在官网下载最新版本的Nodejs装置的流程非常简单,下载软件,依据提醒下一步进而实现装置咱们须要相熟命令行的相干操作,此处不做赘述,能够参考ES6局部课程中的命令行操作创立app.js文件,运行Node代码console.log("Hello Nodejs") 全局对象Nodejs提供了很多全局对象,这些对象能够间接应用,不须要做独自的引入例如:在js中的日志信息打印就是其中之一,文档(opens new window)console.log("测试");定时器也是其中之一,文档(opens new window) var time = 0;var timer = setInterval(function() { time += 2; console.log(time + " seconds have passed"); if (time > 5) { clearInterval(timer); }}, 2000);还用一些罕用的全局对象例如: console.log(__dirname); // 取得以后门路console.log(__filename); // 取得以后门路及文件名字 回调函数咱们须要相熟一下回调函数,因为在整个Nodejs中,满满的都是回调函数 咱们先看上面的根底代码 function sayHi(){ console.log("hi");}var sayBye = function(){ console.log("bye");}sayHi();sayBye();以上是两种函数的申明形式 而后咱们减少回调函数 function sayHi(){ console.log("hi");}var sayBye = function(){ console.log("bye");}sayHi();sayBye();function callFunction(callback){ callback()}callFunction(sayBye);上述代码其中callFunction是一个回调函数,调用了sayBye函数的执行 咱们同样在回调函数中是能够传递参数的 var sayBye = function(name){ console.log(name+":bye");}function callFunction(callback,name){ callback(name)}callFunction(sayBye,'iwen');咱们还能够变换书写形式 function callFunction(callback,name){ callback(name)}callFunction(function(name){ console.log(name+":bye");},'iwen');模块(Commonjs标准)在JavaScript的ES5版本中,最大的问题就是没有模块的概念,然而nodejs中,减少了commonjs标准来解决这一问题。 ...

February 14, 2022 · 6 min · jiezi

关于node.js:使用阿里云npm镜像加速

1.什么是npm?npm(node package manager)是伴随NodeJS一起装置的包管理工具,能解决NodeJS代码部署上的很多问题,常见的应用场景有以下几种:容许用户从NPM服务器下载他人编写的第三方包到本地应用。容许用户从NPM服务器下载并装置他人编写的命令行程序到本地应用。容许用户将本人编写的包或命令行程序上传到NPM服务器供他人应用。因为新版的nodejs曾经集成了npm,所以之前npm也一并装置好了。同样能够通过输出 "npm -v" 来测试是否胜利装置。命令如下,呈现版本提醒示意装置胜利Npm能够了解为一个命令行工具,它的使命就是帮你为我的项目主动装置所依赖的开发包。composer是php包依赖管理工具,node.js包管理工具是npm。能够这么去了解。http://registry.npmjs.org是 npm 的默认的开发包仓库,在npm命令行工具外面咱们能够指定应用不同的仓库。http://registry.npmjs.org是官网的仓库。其余的仓库都是定时同步官网的仓库。也就是说如果切换到其余仓库代码包有肯定的提早。然而切换成国内的镜像源包的下载速度会很快。npm装置插件过程:从http://registry.npmjs.org下载对应的插件包(该网站服务器位于国外,所以常常下载迟缓或出现异常)阿里云官网镜像站:https://developer.aliyun.com/...2.查看npm源地址设置:(默认官网镜像地址)npm config get registryhttps://registry.npmjs.org/3.配置阿里巴巴镜像地址:(举荐,速度够快,同步频率快,稳固)阿里云官网镜像站:https://developer.aliyun.com/...Npm阿里云地址:http://www.npmmirror.comnpm config set registry https://registry.npmmirror.com 原淘宝 npm 域名行将进行解析,正如在《淘宝 NPM 镜像站喊你切换新域名啦》 中预报的那样:http://npm.taobao.org 和 http://registry.npm.taobao.org 将在 2022.06.30 号正式下线和进行 DNS 解析。域名切换规定:http://npm.taobao.org => http://npmmirror.comhttp://registry.npm.taobao.org => http://registry.npmmirror.com 4.如果须要解除镜像并复原到官网源,请执行以下命令:npm config set registry https://registry.npmjs.org

February 14, 2022 · 1 min · jiezi

关于node.js:前端模块化的身份证packagejson

什么是package.json?package.json是JavaScript我的项目的清单,该文件记录了你的我的项目的名称、版本、依赖等相干信息,同时它也是你将我的项目公布到npm上的根据,能够说,package.json在前端模块化时代,相当于我的项目的身份证,充沛理解package.json的用户和含意是前端必备过程 初始化package.json通过npm或者yarn指令能够疾速创立package.json文件: npm init -y// oryarn init -y-y 示意创立默认的package.json,如果不应用-y,则会要求你被动填写json内容。 默认文件内容: { "name": "test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC"}package.json的配置name项目名称,必填字段,默认取的是以后我的项目的文件夹名字。 字段值限度: 长度必须 <= 214个字符,只能蕴含小写字母、'-'和'_'。如果我的项目要公布到npm,必须合乎该标准,即便不须要公布到npm,咱们仍应该准守这样的标准,养成好习惯如果你的我的项目要公布到npm,name就不能与已有的包名反复,在创立package.json之前,咱们能够通过npm指令来查看是否名字反复:npm view package-namepackage-name替换成本人的我的项目名,如果npm上存在对应的包,会返回该包的模块信息,否则返回404 version我的项目版本号,格局为 主版本号.次版本号.订正号,主版本号通常示意做了不兼容的API批改,次版本号通常示意做了向下兼容的的功能性新增,订正号示意做了向下兼容的bug修复 如果版本改变比拟大,运行不稳固,能够先公布后行版本,在惯例版本号前面通过'-'连贯标识符:外部版本(alpha)、公测版本(beta)和候选版本(rc),如: '2.1.0.alpha''2.1.0-beta''2.1.0-rc'后行版本后仍可接小版本后,示意不同的后行版本: '2.1.0.alpha.1''2.1.0.alpha.5'通过npm指令,能够查看线上npm包的最新版本以及版本记录 // 查看最新版本npm view package-name version// 查看所有版本号npm view package-name versiondescription我的项目的简介,让他人晓得你的我的项目是用来做什么的,这在你公布到npm上时特地有用 mainmain指定了我的项目的入口文件,当你制作一个插件公布到npm上后,他人通过import和require等形式导入你的我的项目时,导入的就是main指定的文件,如果不指定main字段,则会在导入时主动寻求根目录下的 index.js、index.json等index命名的文件,如果没有找到,导入就会报错。 scripts定义我的项目node脚本,通过key-value的模式定义脚本名脚本执行内容,前端我的项目中通过 npm run xx 或 yarn xx 执行对应脚本。比方:npm run dev ...

February 14, 2022 · 1 min · jiezi

关于node.js:node项目从0到1实战

前言本文以 koa 框架为例,从0到1 搭建一个后端服务,涵盖了后端服务的根本内容,实现 api 的性能。 适宜人群: 未残缺搭建过node服务的人学写了koa, 想实际的人正在应用 koa 搭建 node 服务的人注释为了实现 api 接口申请,咱们思考几个问题: 整个服务程序的解决流程与错误处理接口路由接口调用权限接口缓存拜访数据库除了服务程序自身,还要思考工程相干的(本文不开展讲): 日志解决监控报警疾速复原认识一下罕用中间件request 参数解析插件参数分3种: url searchurl parameterPOST bodykoa-bodyparser: 把request body 上的数据挂载到 ctx.request.body, 反对 json / text / xml / form (不反对 multipart) 文件缓存相干koa-static: 动态文件系统, 反对 maxage 、gzip 等属性。这个中间件配合上面的中间件更好用: 搭配 koa-conditional-get 做新鲜度检测 和 配合 koa-etag 做协商缓存搭配 koa-mount 做门路管制,比方拜访 /public 时候才去返回文件内容搭配 koa-etag 做 e-tag治理koa-mount:多个子利用合成一个父利用。(也能够用作为通过 path 管制 middleware 的挂载应用 )koa-conditional-get : 让协商缓存失效(304 断定) 缓存机制:https://juejin.cn/post/684490...浏览器缓存: https://segmentfault.com/a/11...koa-etag: 反对 etag/ if-none-match 协商缓存接口缓存接口缓存须要配合 Redis 来做,实现接口高速缓存。 ...

February 10, 2022 · 4 min · jiezi

关于node.js:nodejs中的异常错误处理

异样解决是程序运行中必须要关注的中央,当异样呈现后,应该第一工夫关注到,并且疾速解决。大部分程序员们都不敢保障本人的代码百分比正确,所以应该在写代码时就要对异样提前做预防解决,尽量保障在异样呈现时,给用户一个敌对的提醒,不至于服务挂起导致申请超时,并且能将异样信息做记录上报,不便前期排查解决。 一. 同步代码的异样捕捉解决 同步代码中的异样应用try{}catch构造即可捕捉解决。 try { throw new Error('错误信息');} catch (e) { console.error(e.message);}能够失常捕捉到。 二. 异步代码的错误处理 try/catch 接口异步代码下应用try{}catch构造捕捉解决成果如何呢? try { setTimeout(()=>{ throw new Error('错误信息'); })} catch (e) { console.error('error is:', e.message);}然而却没有捕捉到异步谬误。 process的uncaughtException事件那异步谬误该怎么解决呢?首先换个思维,因为异样并不是当时筹备好的,不能管制其到底在哪儿产生,所以站更高的角度,如监听利用过程的谬误异样,从而捕捉不能意料的谬误异样,保障利用不至于奔溃调。 process.on('uncaughtException', (e)=>{ console.error('process error is:', e.message);});如上代码从process上监听uncaughtException事件,能够捕捉到整个过程蕴含异步中的错误信息,从而保障利用没有奔溃。 然而新的问题随之而来,因为异样不可意料的产生后,当异样呈现时,间接从对应执行栈中断,而到process捕捉的异样事件下,导致了v8引擎的垃圾回收性能不能依照失常流程工作,而后开始呈现内存透露问题。 绝对于异样来说,内存透露也是一个不能漠视的重大问题,而process.on('uncaughtException')的做法,很难去保障不造成内存的透露。所以当捕捉到异样时,显式的手动杀掉过程,并开始重启node过程,即保障开释内存,又保障了保障服务后续失常可用。 process.on('uncaughtException', (e)=>{ console.error('process error is:', e.message); process.exit(1); restartServer(); // 重启服务});然而下面的做法有一点间接,大家未免存纳闷,如果单过程单实例的部署下,杀掉过程在重启这一段时间内服务不能失常可用怎么办?这显然是不合理的。 应用domain模块domain模块,把解决多个不同的IO的操作作为一个组。注册事件和回调到domain,当产生一个谬误事件或抛出一个谬误时,domain对象会被告诉,不会失落上下文环境,也不导致程序谬误立刻退出,与process.on('uncaughtException')不同。Domain 模块可分为隐式绑定和显式绑定:隐式绑定: 把在domain上下文中定义的变量,主动绑定到domain对象显式绑定: 把不是在domain上下文中定义的变量,以代码的形式绑定到domain对象 const domain = require('domain');const d = domain.create();d.on('error', (err) => { console.log('err', err.message); console.log(needSend.message);});const needSend = { message: '须要传递给错误处理的一些信息' };d.add(needSend);function excute() { try { setTimeout(()=>{ throw new Error('错误信息'); }); } catch (e) { console.error('error is:', e.message); }};d.run(excute);domin显著的长处,能把出问题时的一些信息传递给谬误处理函数,能够做一些打点上报等解决工作,最起码保障重启后的服务,程序猿们晓得产生了什么,有线索可查,也能够抉择传递上下文进去,做一些后续解决。比方当服务出错的时候,能够把用户申请栈信息传给上游,返回告知用户服务异样,而不是用户始终等到申请主动超时。 ...

February 9, 2022 · 1 min · jiezi

关于node.js:前端图床搭建实践后端篇

我的项目背景 前端开发过程中经常须要用到的图片等资源,除了应用常见的第三方图床外,咱们也能够本人搭建一个公有图床,为团队提供前端根底服务。本文旨在回顾总结下自建图床的后端局部实现计划,心愿可能给有相似需要的同学一些借鉴和计划。另外说一下,因为是前端根底建设,这里咱们齐全由前端同学所相熟的node.js来实现所须要的后端服务需要。 计划后端局部架构选型,因为这里次要是为前端业务开发人员提供基建服务,而团体平台也提供了各种云服务,并且并不会呈现过多的高并发等场景,因此在语言选择上还是以前端同学所相熟的node.js为主,这里咱们团队次要以express框架为主,在整个大的专网技术团队中,后端依然以java为主,node次要作为中间层BFF来对局部接口进行开发聚合等,因此主体依然以单体架构为主,微服务模式则采纳service mesh的云服务产品(如:istio)来和java同学进行配合,而没有采纳一些node.js的微服务框架(比方:nest.js中有微服务相干的设置,以及seneca等)。因为是单体利用,鉴于express的中间件机制,通过路由对不同模块进行了拆散,本图床服务中提供的服务都隔离在imagepic的模块下;在数据库抉择方面,图床这里仅仅须要一个鉴权机制,其余并没有特地额定的长久化需要,这里我抉择了mongodb作为数据库长久化数据(ps:云中间件提供的mongodb呈现了接入问题,后续通过CFS(文件存储系统)+FaaS来实现了代替计划);因为图床性能的特殊性,对于上传图片进行了流的转换,这里会用到一个长期图片存储的过程,通过云产品的CFS(文件存储系统)来进行长久化存储,定期进行数据的删除;而真正的图片存储则是放在了COS(对象存储)中,相较于CFS的文件接口标准,COS则是基于亚马逊的S3标准的,因此这里更适宜于作为图片的存储载体 目录db \_\_temp\_\_imagepicdeploy dev Dockerfilepv.yamlpvc.yamlserver.yamlproduction Dockerfilepv.yamlpvc.yamlserver.yamlbuild.shfaas index.jsmodel.jsoperator.jsread.jsutils.jswrite.jsserver api openapi.yamllib index.jscloud.jsjwt.jsmongodb.jsroutes imagepic authbucketnotificationobjectpolicyindex.jsminio.jsrouter.jsutils index.jsis.jspagination.jsreg.jsuuid.jsapp.jsconfig.jsindex.jsmain.js实际 对波及到局部接口须要进行鉴权判断,这里应用的是jwt进行相干的权限校验 源码faas这里形象进去了云函数来为后端服务提供能力,模仿实现相似mongodb相干的一些数据库操作 model.js定义的model相干的数据格式 /** * documents 数据结构 * @params * _name String 文件的名称 * _collections Array 文件的汇合 * @examples * const documents = { * "_name": String, * "_collections": Array * } */exports.DOCUMENTS_SCHEMA = { "_name": String, "_collections": Array}/** * collections 数据结构 * @params * _id String 汇合的默认id * _v Number 汇合的自增数列 * @examples * const collections = { * "_id": String, * "_v": Number, * } */ exports.COLLECTIONS_SCHEMA = { "_id": String}read.jsnode的fs模块读文件操作 ...

February 8, 2022 · 11 min · jiezi

关于node.js:低代码搞了个客户关系管理系统-CRM

新增客户关系治理(CRM)零碎/模板(面向企业)欢送观摩,应用收费! 无远客户关系治理精简版,面向企业客户,反对客户打标签、销售漏斗、自定义销售阶段、自定义客户分类等等,你能够联合本公司的理论状况,进一步自主实现赢单后的销售绩效提成功能模块。 预览地址: https://previewer.wuyuan.io/p...  用户名/明码:3 / 123(需先登录开发平台账号) 工作台配置地址:https://workbench.wuyuan.io/p... 【预览图】 客户公海 我的客户 (看到下面这样的工作界面,能够一一电话(SAORAO)客户,有没有想当一把销售的激动?)  客户详情 我的销售统计 销售统计分析(领导视角) 销售参数配置 如何应用? 在开发工作台模板库中即可间接引入应用,【残缺零碎版】有11个页面蕴含了对于行政区表、用户表的根底性能实现,如果只心愿应用销售相干的性能页面,跟本人现有我的项目的用户对接,能够应用【客户关系治理模板】,表构造字段不对用户表有依赖,不便本人批改。

February 8, 2022 · 1 min · jiezi

关于node.js:Kubernetes-生产部署实录-基于-sealos-部署-lafjs

阐明lafyun.com 是基于开源云开发平台 laf.js 部署的公开经营版云开发平台。 lafyun.com 内测阶段是基于 docker-compose 部署的单机版,当初平台正式凋谢公测,须要基于 kubernetes 部署集群版。 环境筹备Kubernetes 的部署采纳 sealos 一键部署。 零碎抉择了 centos 7.9,最后经重复测试过 Aliyun Linux 3.x,Kubernetes 体现极不稳固,零碎常常会因为 OOM 宕机或断连等问题,特地是单次启动 pod 数量过百之后,后抉择了 centos 7.9 体现极其稳固。 kubernetes 抉择了 v1.23.2,此版本默认已不反对 docker ,故容器运行时应用了 containerd。 装置 sealos# install sealos wget -c https://sealyun.oss-cn-beijing.aliyuncs.com/latest/sealos && chmod +x sealos && mv sealos /usr/bin # download sealos kubenetes packagewget -c https://sealyun.oss-cn-beijing.aliyuncs.com/28bdc92bd542d599b6ef021b8c2d7886-v1.23.2/kube1.23.2.tar.gz部署 kubernetes把上面节点的IP换成服务器的内网IP即可,确保 master & node 的 ip 相互可连通后: # init & run the clustersealos init --user root \ --master 172.17.xx.xx \ --node 172.17.xx.yy \ --node 172.17.xx.zz \ --pkg-url /root/kube1.23.2.tar.gz \ --version v1.23.2 \ --podcidr 10.160.0.0/12查看节点运行状态,在 master 节点运行: ...

February 4, 2022 · 1 min · jiezi

关于node.js:如何使用-f2json-丝滑地处理本地文件

你肯定遇到过在node中须要读写本地文件的状况,比方在咱们的需要中须要读取一个本地的json文件,并批改其中的内容最终保留。 通常的做法是须要 import 对应的json文件在你的代码中,但这样做会有一个麻烦就是你能够在你的代码中引入的数据,但这个数据始终是你第一次引入的数据,如果咱们中途须要批改这个 json 文件咱们须要应用fs模块对本地的json文件进行从新地写入操作,这个过程十分的麻烦。如果咱们须要从新获取批改的数据那么就要从新应用fs模块进行读取,这样咱们的代码中就会多出许多文件读写的操作。 对于这样的需要明天介绍一个十分好用的工具库 f2json 它能够不便咱们读写本地文件的操作,并且能够应用像 import语句那样的门路来读写绝对的文件。 首先咱们通过 npm 来装置它 npm install f2json假如咱们的目录构造是这样的 project├── src│ ├── core│ ├── index.js│ │ │ │ └── data.json咱们须要在 index.js中操作我的项目根目录下的data.json index.js: const f2json = require('f2json')() const {json,ok} = f2json.file2json("../../data.json") // do something with json ok() // 调用 ok 会将批改过的json数据主动保留到data.json中这样咱们就能够十分不便地去操作我的项目中的 json文件又或者是其余格局的文件 。 相干链接: f2json的文档: github

February 1, 2022 · 1 min · jiezi

关于node.js:Node-http模块

htttp模块Node自带的服务器模块应用:const http = require('http')应用http搭建一个简略的服务器const http = require('http')// 创立一个Server实例let server = http.createServer()// 注册request 申请事件// 回调函数中两个参数,第一个是request,申请对象,第二个是response,响应对象server.on('request',function(req,res) { console.log('收到申请') // 能够设置Content-Type,比方中文显示会乱码,设置后中文就不是乱码了 // text/plain: 一般文本 // text/html: html res.setHeader('Content-Type','text/plain;charset=utf-8') // res对象有一个办法,write能够用来给客户端发送响应数据 // write能够应用屡次,然而最初肯定要应用end来完结响应,否则客户端会始终期待 res.write('Hello World') res.write('Hello Node') res.write('服务器返回字段') // res.end() // 当然数据也能够在end中间接返回,不必写write res.end('Hello Http')})// 绑定端口号,启动服务器server.listen(9527,function() { console.log('启动胜利,能够通过http://localhost:9527')})给本地文件搭建一个服务器const http = require('http')const fs = require('fs')// 创立一个Server实例let server = http.createServer()// 设置一个本地文件的根目录const baseUrl = 'D:/work/Node/03_http/asstes'// 注册request 申请事件// 回调函数中两个参数,第一个是request,申请对象,第二个是response,响应对象server.on('request',function(req,res) { // 获取拜访的资源门路 let url = req.url // 设置默认的拜访门路 let defaultUrl = '/index.html' if(url !== '/') { defaultUrl = url } // 依据要拜访的门路和根门路拼接 let path = baseUrl + defaultUrl // 读取文件,返回信息给到页面显示 fs.readFile(path,function(err,data) { if(err) { res.end('404') }else { res.end(data) } }) })// 绑定端口号,启动服务器server.listen(9528,function() { console.log('启动胜利,能够通过http://localhost:9528')})

January 28, 2022 · 1 min · jiezi

关于node.js:Node-fs文件系统

什么是fs(文件系统)file system在Node中,与文件的交互是十分重要的,服务器的实质就是将本地的文件发送给近程的客户端Node通过fs模块来和文件系统进行交互该模块提供了一些标准文件拜访API来关上,读取,写入文件,以及其余的交互Node中应用fs模块,const fs = require('fs')fs中的同步和异步fs模块中的所有操作都有两种操作模式,即同步和异步同步文件系统会阻塞零碎的执行,也就是除非操作实现,否则代码不会往下继续执行了异步文件系统不会阻塞程序的执行,而是在操作实现是,通过回调函数将后果返回fs的应用文件写入手动操作的步骤 关上文件 同步:fs.openSync(path[, flags[, mode]]) path:要关上的文件的门路flags:关上文件要做的操作类型(上面会具体介绍有多一些操作类型) r:只读的w:可写的a: 追加mode:可选值,是设置文件的操作权限,个别不传该办法会返回一个文件的描述符作为后果,咱们能够通过该描述符来对文件进行各种操作异步:fs.open(path[, flags[, mode]], callback) callback:两个返回参数 err:谬误对象,如果没有就是nullfa:文件的描述符向文件中写入内容 同步:fs.writeSync(fd, string[, position[, encoding]]) fd:文件的描述符,须要传递要写入的描述符string:要写入的内容position:个别不写,示意写入的起始地位encoding:个别不写,示意编码,默认utf-8异步:fs.write(fd, string[, position[, encoding]], callback)保留并敞开文件 fs.closeSync(fd) fd:要敞开文件的描述符fs.close(fd[, callback])// 同步写入文件const fs = require('fs')// 关上文件let fd = fs.openSync('demo.txt','w')// 写入文件fs.writeSync(fd, "仙剑奇侠传三")// 敞开文件fs.closeSync(fd)// 异步写入文件const fs = require('fs')// 关上文件fs.open('demo2.txt','w',function(err,fd) { if(!err) { // 写入文件 fs.write(fd,'恋情公寓',function(err) { if(!err) { console.log('写入胜利') } // 敞开文件 fs.close(fd,function(err) { if(!err) { console.log('已保留并敞开文件') } }) }) }else{ console.log('出错了') }})简略文件写入 ...

January 28, 2022 · 1 min · jiezi

关于node.js:Node-Buffer缓冲区

Buffer(缓冲区)Buffer的构造和数组很像,操作方法和数组也相似数组中不能存储二进制文件,而Buffer就是专门用来寄存二进制数据的它的元素为16进制的两位数。一个元素就代表一个字节 所以Buffer中每一个元素的范畴都是00-ff之间00-ff转换成二进制就是00000000-11111111,这也是咱们计算机最底层的一个0或者1,咱们称之为1位(bit),8bit = 1byte(字节)在Buffer中存储的是二进制数据,然而显示的时候都是以16进制显示Buffer中内存不是通过JavaScript调配的,而是底层通过C++申请的,也就是咱们能够间接通过Buffer来创立内存中的空间 let str = 'Hello World'// 将一个字符串转换为Bufferlet bufStr = Buffer.from(str)// 如何转换成字符串呢?let newStr = bufStr.toString()console.log(bufStr)// <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>console.log(newStr)// Hello World创立指定大小的BufferBuffer的大小,一旦创立好就能批改了老的办法,Buffer构造函数的形式,不举荐应用,官网说行将废除 // 创立一个10个字节的Bufferlet buf = new Buffer(10)新的形式一:alloc // 创立一个10个字节的Bufferlet buf = Buffer.alloc(10)buf[0] = 66buf[1] = 255buf[2] = 0xaa // 这些写法是间接赋值一个16进制的数据,16进制的数据,就是`0x`结尾console.log(buf)console.log(buff[2]) // 后果是170,为什么不是aa呢?因为只有数字在控制台或页面中输入,肯定是10进制新的形式二:allocUnsafe // 创立一个10个字节的Buffer// 和alloc根本一样,只是allocUnsafe创立的Buffer中可能会含有敏感数据// 什么意思呢?alloc在创立的时候,会清空那一块内存,而allocUnsafe不会清空,也就是说之前的数据,可能会泄露进去// 既然如此,为什么还要allocUnsafe呢?因为allocUnsafe的效率更高,然而咱们失常来说还是应用alloclet buf = Buffer.allocUnsafe(10)console.log(buf)

January 28, 2022 · 1 min · jiezi

关于node.js:NodeJS模块化

NodeJS遵循commonJs的语法标准引入:require()导出:module.exports或者exportsNode中的模块化在Node中,一个JS就是一个模块在Node中,每一个JS文件的js代码都是独立运行在一个函数中,而不是全局作用域 怎么证实是一个函数呢?咱们能够输入只有函数有的:console.log(arguments)当咱们输入 console.log(arguments.callee + ''),就会发现,输入的是一个函数。(arguments.callee保留的就是以后的函数)这个函数就长这样: // exports:该对象用来将变量或者喊出裸露到内部// require:函数,用来引入内部模块// module:module代表的是以后的模块自身,exports就是module的一个属性。所以咱们即能够应用exports导出也能够应用module.exports导出// __filename:以后文件的一个残缺门路// __dirname:以后文件所在的文件夹的门路function (exports, require, module, __filename, __dirname) {// 我在01_module.js输入的,显示的就是我以后js文件这个函数const md = require('./02_module')console.log(md.name)console.log(md.num)console.log(md.sayHi())console.log(arguments.callee + '')}在Node中,一个模块中的变量和函数在其余函数中无奈间接拜访。咱们能够通过exports或者module.exports向内部裸露变量和办法在Node中,通过require()函数来引入内部模块 require()能够传递一个文件的门路作为参数,Node将会主动依据该门路来引入内部模块留神的是,这里的门路,如果应用相对路径,必须以./或者../结尾,不能省略。应用require()引入模块后,该函数返回一个对象,这个对象代表的就是引入的模块简略说下module.exports和exports区别其实exports = module.exports。exports只能应用.的模式向里面裸露外部的变量 exports.x = xxxmodule.exports既能够通过.的模式,也能够应用间接赋值 mudule.exports.x = xxxmodule.exports = {}为什么exports不能应用间接赋值呢?这波及到数据的类型和内存(数据寄存地位) 数据的类型分为值类型和援用类型,值类型又叫根本数据类型或者简略数据类型,援用类型又叫简单数据类型内存分为站内存和堆内存。咱们的值类型是间接放在栈内存中,每个数据之间互相独立。援用类型的数据是放在堆内存中的,然而它有个寄存地址,这个地址是放在栈内存中的。 // 值数据类型,变量a寄存在栈内存中,值为100var a = 100// 援用数据类型,变量b寄存在栈内存中,值是援用类型数据在堆内存中的地址,而援用尅性的数据自身寄存在堆内存中var b = { name: '景天', age: 18}exports = module.exports,原本export是指向module的exports,然而如果咱们应用exports = {},那么export的指向就扭转了,不再指向module.exports。NodeJS模块中分成两大类外围模块 由Node引擎提供的模块外围模块的标识就是名字文件模块 由用户本人创立的模块文件模块的标识,就是文件的门路。简略的demo// 01_module.js----引入const md = require('./02_module')const fs = require('fs')console.log(md.name)console.log(md.num)console.log(md.sayHi())// 02_module.js----导出console.log(111111)// exports导出exports.name = '模块2中的A'exports.num = 1000exports.sayHi = function() { console.log(`大家好`)}// module.exports导出形式1module.exports.name = '模块2中的A'module.exports.num = 1000module.exports.sayHi = function() { console.log(`大家好`)}// module.exports导出形式2module.exports = { name: '模块2中的A', num: 1000, sayHi: function() { console.log(`大家好`) }}

January 28, 2022 · 1 min · jiezi

关于node.js:关于-Nodejs-之-Buffer

JavaScript 语言本身只有字符串数据类型,没有二进制数据类型。 但在解决像 TCP 流或文件流时,必须应用到二进制数据。因而在 Node.js 中,定义了一个 Buffer 类,该类用来创立一个专门寄存二进制数据的缓存区。 在 Node.js 中,Buffer 类是随 Node 内核一起公布的外围库。Buffer 库为 Node.js 带来了一种存储原始数据的办法,能够让 Node.js 解决二进制数据,每当须要在 Node.js 中解决 I/O 操作中挪动的数据时,就有可能应用 Buffer 库。 原始数据存储在 Buffer 类的实例中。 一个 Buffer 相似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。 创立 Buffer 类Node Buffer 类能够通过多种形式来创立。 办法 1 创立长度为 10 字节的 Buffer 实例: var buf = new Buffer(10);办法 2 通过给定的数组创立 Buffer 实例: var buf = new Buffer([10, 20, 30, 40, 50]);办法 3 通过一个字符串来创立 Buffer 实例: var buf = new Buffer("bianchengsanmei", "utf-8");utf-8 是默认的编码方式,此外它同样反对以下编码:"ascii", "utf8", "utf16le", "ucs2", "base64" 和 "hex"。 ...

January 25, 2022 · 3 min · jiezi

关于node.js:最简单的-nodejs-百度-ocr身份证识别demo

创立一个文件夹装置一个 申请工具 我用的 reqwest,还须要xhr2 代码如下 const reqwest = require("reqwest");const path = require("path");const fs = require("fs");(async function () { //获取access_toekn 30天无效 let access_token = await get_access_token() //读取身份证,转为base64 var data = fs.readFileSync(`./sfz/1.jpg`); data = data.toString('base64'); //间接申请,相干api+access_token //参数两个必传项, //image: base64图片, //id_card_side: 'front或back' 正反面的意思 let res = await reqwest({ url: 'https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=' + access_token, contentType: 'application/x-www-form-urlencoded', method: "post", data: { image: data, id_card_side: 'front' } }) console.log(res)//这里就是后果了})()//获取access_token 但写的办法async function get_access_token() { let res = await reqwest({ method: 'post', type: 'json', url: 'https://aip.baidubce.com/oauth/2.0/token', data: { 'grant_type': 'client_credentials', 'client_id': 'appid',//百度提供 'client_secret': 'appkey'//百度提供 } }) return res.access_token}

January 25, 2022 · 1 min · jiezi

关于node.js:docsify搭建你的个人博客

因为看了codesheep大佬的视频, https://www.bilibili.com/vide... 所以总结了一下装置步骤,和一些踩坑的点 必备软件装置node.js执行指令npm install -g docsify-cli 装置docsify创立文件夹repository 而后cd到此目录下docsify init下载资源,公众号codesheep,回复:知识库把README替换docsify serve 启动网页服务器在html文件中,开启封面和导航搞一个云服务器,抢阿里云的秒杀 esc看部署文档,装置nginx本地装置xftp,上传目录repository,xshell近程连贯服务器把目录上传到服务器开启esc阿里云服务器的80端口,这样外网能力拜访最好申请一个域名,我目前申请中...

January 21, 2022 · 1 min · jiezi

关于node.js:node-与-tsnode

写在后面node 是 javascript 语言的一个执行环境,能够间接执行 javascript 代码。随着前端技术的须要,在 javascript 语言的根底上扩大创造了 typescript 语言,typescript 语言是 javascript 扩大而来的一个超集。typescript 的语法查看能帮忙进步编程的效率和缩小出错率,因而在前端技术中被宽泛使用。 然而 typescript 语言没有对应的执行环境,须要通过编译成 javascript 后执行。将 typescript 语言编译成对应的 javascript 语言的工具有很多,比方 npm 上的 typescript 包,Vscode 中的 TypeScript 插件等等。 每次执行 typescript 语言都要先手动转化成 javascript 语言,再用 node 执行 js ,那能不能提供一个环境能间接执行 ts 呢?因而 ts-node 就被创造进去了。ts-node 是 typescript 语言的执行环境,就像 node 是 javascript 语言的执行环境一样。 ts-node 也是基于 node 的,在 node 执行的 hook 里主动进行了 ts->js 的语言编译,使得 ts 能够被间接执行。 node 执行 js// a.jsconsole.log('我是 a');在控制台用 node 执行如下 ...

January 20, 2022 · 1 min · jiezi

关于node.js:后端工作笔记

一、已存在数据的表中增加一个字段@Index设置索引的须要留神的场景复现:1、在一张有数据的表中须要增加字段2、凑巧这个字段须要设置索引,且是惟一索引3、这时typeOrm自动更新表的时候会报错,因为这张表中曾经存在的数据的此项新增字段为空,且你又设置为惟一索引,就会报错解决办法:1、 先设置@Index 非惟一索引2、 而后往表中已存在的数据此字段处增加数据(惟一字符串之类的数据)3、 再设置此表为@Index({ unique: true })4、 留神:在本地数据库和远端数据库同步时也要留神这个问题,只能先同步非惟一索引的设置,同步完表构造,而后增加完惟一数据,再同步设置惟一索引

January 19, 2022 · 1 min · jiezi

关于node.js:看看CabloyJS是如何实现编辑页面脏标记的

利用场景咱们在应用Word、Excel时,当批改了内容之后在标题栏会显示脏标记,从而能够明确的告知用户内容有变动。此外,如果在没有保留的状况下敞开窗口,零碎会弹出提示框,让用户抉择是否放弃批改 那么,在Web零碎中,咱们是否也能够反对这种脏标记机制呢? 答案是必定的,CabloyJS就提供了这种脏标记机制,而且CabloyJS内置的所有能够编辑的页面都反对了这种成果 成果演示 如何应用上面以模块test-party为例,演示如何向编辑页面增加脏标记机制。演示代码都在上面的文件中: src/module-vendor/test-party/front/src/kitchen-sink/pages/markdownEditor.vue 1. 引入脏标记组件import Vue from 'vue';const ebPageDirty = Vue.prototype.$meta.module.get('a-components').options.mixins.ebPageDirty;export default { mixins: [ebPageDirty], ...}ebPageDirty是由模块a-components提供的组件,放入以后页面组件的mixins中 2. Title显示脏标记<template> <eb-page>3. <eb-navbar :title="page_title" eb-back-link="Back"> ... </eb-navbar> </eb-page></template><script>import Vue from 'vue';const ebPageDirty = Vue.prototype.$meta.module.get('a-components').options.mixins.ebPageDirty;export default { mixins: [ebPageDirty], ... computed: { page_title() {16. const title = this.$text('Markdown Editor');17. return this.page_getDirtyTitle(title); }, },};</script>行16:获取国际化解决后的题目行17:调用page_getDirtyTitle办法向title动静增加脏标记行3:动静绑定page_title3. 批改脏标记export default { ... methods: { async onPerformSave() { if (!this.$refs.editor) return; await this.$refs.editor.checkContent(); this.$view.toast.show({ text: this.$text('Saved') });8. this.page_setDirty(false); }, onInput(data) { if (this.content === data) return; this.content = data;13. this.page_setDirty(true); }, },};行13:当用户输出内容时,调用page_setDirty办法将脏标记置为true行8:当保留内容时,调用page_setDirty办法将脏标记置为false组件ebPageDirty的办法名称阐明 page_getDirtyTitle向Title动静增加脏标记 page_setDirty批改脏标记 相干链接文档: https://cabloy.com/GitHub: https://github.com/zhennann/c...

January 18, 2022 · 1 min · jiezi