Node.js相关
JS 是客户端编程语言,通过 Node.js,JS也可以服务端语言被使用。
使用 npm 初始化新项目,命令行工具运行: npm init
根据提示输入 package name、version number、description。通过 enter 键跳过,最终生成 package.json 文件。
检查 node 版本
node -v
偶数版本号的为稳定版
命令行工具输入 node
,进入 Node.js 环境。连续2次 Ctrl+C 退出 Node.js 环境。
在命令行模式下运行 .js 文件和在 Node.js 环境下直接运行 JavaScript 代码展示效果不同。
Node.js 环境每输入一行代码就执行一行(每行 JavaScript 代码的结果会自动打印出来),直接运行 JavaScript 文件,相当于一次性执行所有源代码,除非使用console打印,否则输出没有显示。
单线程执行
Node.js不断执行响应事件的JavaScript函数,直到没有任何响应事件的函数可以执行时退出。
通过调用 process.nextTick()
可以在下一次事件响应中执行相应代码。
模块
在Node环境中,一个.js文件就称之为一个模块(module)。使用模块的好处:提高了代码的可维护性,避免函数名和变量名冲突。
Node.js 利用 JavaScript 的函数式编程的特性,使用闭包实现模块的隔离。
模块输出: module.exports = 变量名
Node 在加载js文件前先准备一个对象 module
,并将其作为函数参数传入加载函数,
模块引用: var 变量名 = require('./文件A');
Node 保存了所有导入的 module,当我们用 require()
获取module时,Node找到对应的module,把这个module的 exports 变量返回
上面表示模块的相对路径,即在当前目录下的A文件。如果去掉 ./
,则依次在内置模块、全局模块和当前模块下查找A文件。
Node.js内置的常用模块就是为了实现服务器程序的基本功能:接收网络请求,读写文件,处理二进制内容。
import Router from ‘vue-router’
能够正确引用 mode_modules 目录下的文件的原理是什么?以及具体引用哪个文件?
首先看知乎 答案,然后看 Node.js 官方文档
如何寻找 mode_modules 目录下的文件Loading from node_modules Folders,加载哪一个文件Folders as Modules
知道了模块引用原理,可以对第三方包进行 debugger
内置对象
JavaScript有且仅有一个全局对象,在Node.js环境中,这个对象叫 global
.
process
表示当前Node.js进程:可以用来查看当前系统信息,node版本。
> process.platform
'win32'
> process.arch
'x64'
> process.version
'v12.14.0'
fs
该模块为文件系统模块,同时通过了异步和同步的方法。
因为JavaScript的单线程模型,执行IO操作时,使用异步方法的JavaScript代码无需等待,而是传入回调函数后,继续执行后续JavaScript代码.
通过 fs.stat(filepath, callback)
可以获取文件的信息(大小、创建时间、修改时间等)。
同步读文件
var fs = require('fs');
var data = fs.readFileSync('sample.txt', 'utf-8');
console.log(data);
因为函数直接返回结果,需要用 try…catch 捕获文件读取发生的错误.
异步读文件
var fs = require('fs');
fs.readFile('sample.txt', 'utf-8', function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
Node.js标准的回调函数:第一个参数代表错误信息,第二个参数代表结果。
当正常读取时,err 参数为 null
,data 参数为读取到的String。当读取发生错误时,err 参数代表一个错误对象,data 为 undefined
.
当读取二进制文件时,不传入文件编码(第二个参数)时,回调函数的 data 参数将返回一个 Buffer 对象。
Node.js 提供了Buffer对象和String互相转换的方法。
异步写入文件
var fs = require('fs');
var result = { 'id': 1 };
fs.writeFile('./result.json', JSON.stringify(result), (err) => {
if (err) {
// 报错:
// 意外错误
// 文件权限问题
// 文件夹找不到(不会自动创建文件夹)
console.log(err);
} else {
console.log('success');
}
});
第二个参数表示传入的数据, 如果其类型为 String,默认按 UTF-8 编码写入文本文件;如果传入的参数是 Buffer,则写入的是二进制文件.
stream
该模块用来支持“流”这种数据结构。
流的特点是数据是有序的,而且必须依次读取,或者依次写入,不能像Array那样随机定位。
在 Node.js中,流是一个对象,通常是文件流。
以流的形式读取文件,通过响应流的事件:data 事件表示流的数据已经可以读取了(该事件可以用有多次,每次传入的chunk是流的一部分),end 事件表示没有数据可以读取了,error 事件表示出错了。
// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');
以流的方式写入文件,通过调用 write() 方法,最后以 end() 结束。
// 写入一个流
var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream写入文本数据...\n');
ws1.write('END.');
ws1.end();
通过 pipe()
方法把一个 Readable 文件流和另一个 Writable 文件流串起来,可实现复制文件内容(后者内容完全被覆盖)。
http
该模块提供的 request
和 response
对象。前者的属性和方法可以拿到 HTTP 请求的信息,后者的方法可以把 HTTP 响应返回浏览器。
path
该模块可以用来方便地构建操作系统的文件路径。
var path = require('path');
// 解析当前目录:
var workDir = path.resolve('.');
// 拼接本地文件路径
var filepath = path.join(workDir, 'index.html');
// d:\xue_w\Documents\dive-into-web\index.html
crypto
Nodejs用C/C++实现通用的加密和哈希算法,通过 cypto 这个模块暴露为JavaScript接口提供,使用方便,运行速度快。
crypto模块也可以处理数字证书,通常用在SSL连接。一般情况下,https连接只需要处理服务器端的单向认证,如无特殊需求(例如自己作为Root给客户发认证证书),建议用反向代理服务器如Nginx等Web服务器去处理证书。
const crypto = require('crypto');
// 如果要使用SHA1,把md5换成 SHA1 即可
const hash = crypto.createHash('md5');
// 可任意多次调用update(),默认输入字符串编码为UTF-8,也可以传入Buffer
hash.update('Hello, world!');
hash.update('Hello, nodejs!');
console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544
还可以使用更安全的 sha256、sha512。
对称加密算法 AES
加解密使用同一个密钥,需要自己封装函数。加密结果通常有两种表示方法:hex 和 base64。当通信双方使用不同语言时,要确认双方是否遵循同样的AES算法,字符串密钥、IV是否相同,加密后的数据格式是否统一。
非对称加密算法 RSA
由一个私钥和一个公钥构成的密钥对,通过私钥加密,公钥解密,或者通过公钥加密,私钥解密。
web开发框架
Express 是第一代Node.js web框架,基于ES5的语法,通过回调实现异步代码。Express团队基于ES6重新编写了下一代框架,即koa1。目前,该团队已基于ES7编写了koa2,完全使用 Promise 配合 async 来实现异步。
koa2
每收到一个http请求,koa就会调用通过 app.use()
注册的 async 函数,然后用await next()来调用下一个async函数。每个async函数称为 middleware,这些 middleware 可以组成处理链,依次完成相应的任务。
注意:调用 app.use() 的顺序决定了 middleware
如果一个 middleware 没有调用 await next(),那么后续的middleware将不再执行。
app.use(async (ctx, next) => {
if (await checkUserPermission(ctx)) {
await next();
} else {
// 用户权限校验不通过,则直接返回
ctx.response.status = 403;
}
});
常用的middleware:
- koa-router,负责处理URL映射的middleware
- koa-bodyparser,解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中(不论Node.js提供的原始request对象,还是koa提供的request对象,都没提供解析request的body的功能)
模板引擎
基于模板,根据输入的数据,输出文本的一个组件。通常是输出HTML文本,也可以是Text,XML,Markdown等。
通常需要具备的功能:
- 对特殊字符进行转义,如
<scrit>
标签 - 格式化,如货币、日期时间值展示
- 支持简单的逻辑,如:条件判断、循环输出等
- 模板继承
MVC
最初接触web编程时学习的概念:Model-View-Controller,中文“模型-视图-控制器”。Controller 负责业务逻辑,如:数据库操作,表单提交校验。View 是人看到的一切,比如:模版、HTML页面、CSS样式、JavaScript脚本。负责显示逻辑,替换变量输出用户最终看到的页面。Model 模型即所有数据存储的地方,如:数据库、全局字典。是传给 View 的JS数据对象。
Sequelize数据库
常见的付费数据库有Oracle、SQL Server;免费的有 MySQL、PostgreSQL、sqlite。其中MySQL普及率最高。
访问MySQL是通过网络发送SQL命令给MySQL服务器。这个访问MySQL服务器的软件包通常称为 MySQL 驱动程序。MySQL官方提供了Java、.Net、Python、Node.js、C++和C的驱动程序,官方的 Node.js 驱动目前仅支持5.7以上版本。
数据库每一行数据都可以用一个JavaScript对象表示,这就是传说中的ORM技术:Object-Relational Mapping,把关系数据库的表结构映射到对象上。
Sequelize是Node.js的ORM框架
实战
读取命令行参数
http://nodejs.cn/learn/nodejs-accept-arguments-from-the-command-line
循环打印所有的参数(包括 node 路径和文件路径):
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`)
})
node test.js m 20220609
0: /Users/*/.nvm/versions/node/v16.14.0/bin/node
1: /Users/*/path_to_file/update-theme-name.js
2: m
3: 20220609
仅获取所需参数,改进下:
const args = process.argv.slice(2)
console.log(args[0], args[1])