
工具
NVM
nodejs的版本管理工具
nvm ls

- 列出电脑下所有的nodejs版本,并指出当前版本
nvm use 10.15.0
- 切换当前使用的nodejs版本
nvm install 10.15.0
- 下载并使用版本10.15.0
NPM
nodejs的包管理工具
npm init
- 可以初始化一个package.json文件。在初始化的过程中,会叫用户输入name, version等等信息,当然,你都可以忽略。一路点回车,就生成了下面这样一个初始化的package.json。
package.json
1 | { |
- name: 这个很好理解,就是package的名称。不过需要注意的是,name有长度限制(虽然一般都不会超),而且name不能以 【点】 或者 【下划线】开头,name中不能有大写字母。这个是每一个package必须的。在业务代码中,通过
require(${name})
就可以引入对应的程序包了。 - version: package的版本。对于业务项目来说,这个往往不太重要,但是如果你要发布自己的项目,这个就显得十分重要了。name和version共同决定了唯一一份代码。npm是用[npm-semver]来解析版本号的。我们一般见到的都是
大版本.次要版本.小版本
这种版本号,比如16.1.0
。版本号的规则、含义其实蛮多的,可以参考这篇文章。 - desription:包的描述。开发组件库时必需,简明的向库的使用者介绍这个库是干嘛的。对于公司的业务项目,这个配置项一般无所谓。
- keywords:关键词。一个字符串数组,对这个npm包的介绍。组件库必需,便于使用者在npm中搜索。对于公司业务项目,这个配置一般无所谓。
- homepage: 项目主页。对于开发组件库来说挺有用的。
- bugs:开发者的联系方式,代码库的issues地址等。如果代码使用者发现了bug,可以通过这个配置项找到提bug的地方。
- license:开源协议。对于开源组件库,这个十分重要。之前react还因为这事儿没少被社区嫌弃。开源协议略微复杂,用阮一峰前辈的一张图来说明一下吧。注:图里少了ISC, ISC和BSD差不多

author:项目的作者。可以为字符串,对象。
contributors:项目的贡献者。author的数组。
main:代码入口。这个十分重要,特别是对于组件库。当你想在node_modules中修改你使用的某个组件库的代码时,首先在node_modules中找到这个组件库,第一眼就是要看这个main,找到组件库的入口文件。在这个入口文件中再去修改代码吧。
scripts:指定了运行脚本命令的npm命令行缩写。十分重要。
- 在命令行输入:
npm run dev
, 对应的命令就会被执行。这里有一个地方需要注意,当执行npm run xxx
的时候,node_modules/.bin/
目录会在运行时被加入系统的PATH变量。 - 上面的例子,当我们在命令行输入:
npm run build
时,其实真正执行的命令是node_modules/.bin/webpack
而不是webpack
。所以,当你的webpack并未全局安装时,直接在命令行输入:webpack
是会报错的。因为你的webapck是安装在node_modules/.bin/
下面的。
1
2
3
4
5
6
7"scripts": {
"dev": "NODE_ENV=dev webpack-dev-server --progress --hot --host 0.0.0.0 --port 8089",
"test": "NODE_ENV=test webpack --config webpack.test.config.js --progress",
"online": "NODE_ENV=production webpack --config webpack.online.config.js --progress",
"build": "webpack",
"node": "node server.js"
},- 在命令行输入:
directories:对整个代码结构的描述。告诉代码包使用者可以在哪里找到对应的文件。
files:数组。表示代码包下载安装完成时包括的所有文件。
repository:对于组件库很有用。让组件库使用者找到你的代码库地址。这个配置项会直接在组件库的npm首页生效。例子:
1
2
3
4"repository": {
"type": "git",
"url": "git+https://github.com/CoyPan/react-scroll-to-show-cb.git"
},config:用于添加命令行的环境变量。具体用法见这里。
dependencies:项目的依赖。通过
npm install --save
安装的包会出现在这里。- 注意,不要把测试工具、代码转换器或者打包工具等放在这里。当你在命令行里面使用
npm install react --save
时,react就会出现在dependencies。默认是安装最新的版本。如果想安装某个特定的版本,可以npm install react@15.6.2
。
- 注意,不要把测试工具、代码转换器或者打包工具等放在这里。当你在命令行里面使用
以下的dependencies,格式都是合法的,
1 | "dependencies" : { |
- foo组件的地址为
git+ssh://{foo代码库的ssh地址}#v{foo的版本号}
- 好处:组内的许多项目都有同一个功能,把这个功能抽出来做成组件是很自然的想法。但是每个项目都有自己的代码库,公司也没有内部的npm库,组件应该放在哪里呢?可以专门为组件新建一个代码仓库,将组件放在这里开发、迭代。这样,各个项目都可以引用该组件:只需要在dependencies中将组件配置成上述的形式。至于组件的版本,可以通过
git tag
来控制。
- 好处:组内的许多项目都有同一个功能,把这个功能抽出来做成组件是很自然的想法。但是每个项目都有自己的代码库,公司也没有内部的npm库,组件应该放在哪里呢?可以专门为组件新建一个代码仓库,将组件放在这里开发、迭代。这样,各个项目都可以引用该组件:只需要在dependencies中将组件配置成上述的形式。至于组件的版本,可以通过
- dependencies还有其他的配置方式,具体在这里查看。
- devDependencies:项目的依赖。通过
npm run install --save-dev
安装的包会出现在这里。主要是在开发过程中依赖的一些工具。用法与dependencies相似。 - bundledDependencies:数组,打包时的依赖。如果配置了bundledDependencies,在项目中执行
npm pack
将项目打包时,最后生成的.tgz
包中,会包含bundledDependencies中配置的依赖。bundledDependencies中的依赖必须在devDependencies或者dependencies中声明过。 - peerDependencies: 指定当前组件的依赖以其版本。如果组件使用者在项目中安装了其他版本的同一依赖,会提示报错。
- engines:指定项目所依赖的node环境、npm版本等。
- private:如果设为true,无法通过
npm publish
发布代码。 - bin:用来指定各个内部命令对应的可执行文件的路径。具体用法这里不多讲了。详情可以点击这里。
npm install
- 根据配置文件
package.json
来安装环境 - 会在当前路径下自动创建文件夹
node_modules
,里面放所有下载的依赖包
npm install name --save
- 下载包name,同时加载到配置文件
package.json
的依赖"dependencies"
里面
教程
语法
数据类型
Number
1 | 123; // 整数123 |
- JavaScript不区分整数和浮点数,统一用Number表示,以上都是合法的Number类型
- Number的四则运算同数学
- 注意:
NaN
这个特殊的Number与所有其他值都不相等,包括它自己:- NaN === NaN //false
- isNaN(NaN); //true
字符串
大小写转换
1 | str = 'User'; |
比较运算符
==
:它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;===
:它不会自动转换数据类型,如果数据类型不一致,返回false
,如果一致,再比较。- 由于JavaScript这个设计缺陷,不要使用
==
比较,始终坚持使用===
比较。
- 由于JavaScript这个设计缺陷,不要使用
null和undefined:
null
表示一个“空”的值,它和0
以及空字符串''
不同,0
是一个数值,''
表示长度为0的字符串,而null
表示“空”。- 在其他语言中,也有类似JavaScript的
null
的表示,例如Java也用null
,Swift用nil
,Python用None
表示。但是,在JavaScript中,还有一个和null
类似的undefined
,它表示“未定义”。 - JavaScript的设计者希望用
null
表示一个空的值,而undefined
表示值未定义。事实证明,这并没有什么卵用,区分两者的意义不大。 - 大多数情况下,我们都应该用
null
。undefined
仅仅在判断函数参数是否传递的情况下有用。
数组
对象
strict模式
- JavaScript在设计之初,为了方便初学者学习,并不强制要求用
var
申明变量。这个设计错误带来了严重的后果:如果一个变量没有通过var
申明就被使用,那么该变量就自动被申明为全局变量 - 为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了
strict模式
,在strict模式
下运行的JavaScript代码,强制通过var
申明变量,未使用var
申明变量就使用的,将导致运行错误。
容器
Map
Set
Iterable
变量
- 变量名是大小写英文、数字、
$
和_
的组合,且不能用数字开头。 - 变量名也不能是JavaScript的关键字,如
if
、while
等。 - 申明一个变量用
var
语句
变量输出
- console.log(x)
- alert(x) –html弹窗
环境变量 process.env
1 | var http_port = process.env.HTTP_PORT || 3001 //默认设置为3001 |
process:是一个 global (全局变量),提供有关信息,控制当前 Node.js 进程。
作为一个对象,它对于 Node.js 应用程序始终是可用的,故无需使用 require()。- process(进程)其实就是存在nodejs中的一个全局变量,所有模块都可以调用。
终端设置变量值
1
2
3
4
5
6
7
8
9
10
11
12//win
set HTTP_PORT=3002
set P2P_PORT=6002
set PEERS=ws://localhost:6001
//ios
export HTTP_PORT=3002
export P2P_PORT=6002
export PEERS=ws://localhost:6001
//启动
node file.js- ios
标准对象
- 在JavaScript的世界里,一切都是对象。
- 但是某些对象还是和其他对象不太一样。为了区分对象的类型,我们用
typeof
操作符获取对象的类型,它总是返回一个字符串
1 | typeof 123; // 'number' |
number
、string
、boolean
、function
和undefined
有别于其他类型。- 特别注意:
null
的类型是object
,Array
的类型也是object
,如果我们用typeof
将无法区分出null
、Array
和通常意义上的object——{}
。
包装对象
1 | var n = new Number(123); // 123,生成了新的包装类型 |
- 类型为
object
总结一下,有这么几条规则需要遵守:
不要使用
new Number()
、new Boolean()
、new String()
创建包装对象;- 如果没写
new
,Number()
、Boolean
和String()
被当做普通函数,把任何类型的数据转换为number
、boolean
和string
类型(注意不是其包装类型)
- 如果没写
用
parseInt()
或parseFloat()
来转换任意类型到number
;用
String()
来转换任意类型到string
,或者直接调用某个对象的toString()
方法;null
和undefined
就没有toString()
方法;Object一些情况下也不能使用number
对象调用toString()
报SyntaxError:123.toString(); // SyntaxError 123..toString(); // '123', 注意是两个点! (123).toString(); // '123'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
- 通常不必把任意类型转换为`boolean`再判断,因为可以直接写`if (myVar) {...}`;
- `typeof`操作符可以判断出`number`、`boolean`、`string`、`function`和`undefined`;
- 判断`Array`要使用`Array.isArray(arr)`;
- 判断`null`请使用`myVar === null`;
- 判断某个全局变量是否存在用`typeof window.myVar === 'undefined'`;
- 函数内部判断某个变量是否存在用`typeof myVar === 'undefined'`。
### Date
### RegExp
### JSON
* JSON实际上是JavaScript的一个子集。
* JSON字符集必须是UTF-8
* 为了统一解析JSON的字符串规定必须用双引号`""`,Object的键也必须用双引号`""`。
* 在JSON中,一共就这么几种数据类型:
1. **number**:和JavaScript的`number`完全一致;
2. **boolean**:就是JavaScript的`true`或`false`;
3. **string**:就是JavaScript的`string`;
4. **nul**l:就是JavaScript的`null`;
5. **array**:就是JavaScript的`Array`表示方式——`[]`;
6. **object**:就是JavaScript的`{ ... }`表示方式。
**序列化:** 对象 -> JSON
* `JSON.stringfy(var, null, ' ')`:将nodejs对象输出成标准JSON格式
* 第二个参数用于控制如何筛选对象的键值,如果我们只想输出指定的属性,可以传入`Array`
* `JSON.stringify(xiaoming, ['name', 'skills'], ''); `
* 只输出对象 xiaoming 的 name 和 skills 属性
* 第二个参数还能是一个函数,这样对象的每个键值对都会被函数先处理,
* ```javascript
function convert(key, value) {
if (typeof value === 'string') {
return value.toUpperCase();
}
return value;
}
JSON.stringfy(xiaoming, convert, ' ');
- 第三个参数控制按缩进输出
1 | var xiaoming = { |
- 如果我们还想要精确控制如何序列化小明,可以给
xiaoming
定义一个toJSON()
的方法,直接返回JSON应该序列化的数据:
1 | var xiaoming = { |
反序列化: JSON -> 对象
JSON.parse()
:把JSON变成一个JavaScript对象
1 | JSON.parse('[1,2,3,true]'); // [1, 2, 3, true] |
JSON.parse()
还可以接收一个函数,用来转换解析出的属性:
1 | var obj = JSON.parse('{"name":"小明","age":14}', function (key, value) { |
面向对象
类
构造
1 | class ClassName { |
继承
1 | class Son extends Father{ |
实例化
1 | var son = new Son('cindy'); |
use strict
- 在第一行加上
'use strict'
表示启用严格模式- ES6 的模块自动采用严格模式,不管你有没有在模块头部加上
"use strict";
。
- ES6 的模块自动采用严格模式,不管你有没有在模块头部加上
- 主要限制:
- 变量必须声明后再使用
- 函数的参数不能有同名属性,否则报错
- 不能使用
with
语句 - 不能对只读属性赋值,否则报错
- 不能使用前缀0表示八进制数,否则报错
- 不能删除不可删除的属性,否则报错
- 不能删除变量
delete prop
,会报错,只能删除属性delete global[prop]
eval
不会在它的外层作用域引入变量eval
和arguments
不能被重新赋值arguments
不会自动反映函数参数的变化- 不能使用
arguments.callee
- 不能使用
arguments.caller
- 禁止
this
指向全局对象 - 不能使用
fn.caller
和fn.arguments
获取函数调用的堆栈 - 增加了保留字(比如
protected
、static
和interface
)
模块
module
用来提供nodejs的模块化功能
1 | /* a.js */ |
- 所有的exports收集到的属性和方法,都赋值给了**
Module.exports
。当然,这有个前提,就是Module.exports
本身不具备任何属性和方法。如果,Module.exports
已经具备一些属性和方法,那么exports**收集来的信息将被忽略.
module.exports
模块规范
CommonJS
模块规范和ES6
模块规范完全是两种不同的概念。- CommonJS规范
- ES6 Module 的语法
CommonJS
- Node应用由模块组成,采用CommonJS模块规范。
- 根据这个规范,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
- CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。
- 下面代码通过module.exports输出变量x和函数addX。
1 | var x = 5; |
- require方法用于加载模块。
1 | var example = require('./example.js'); |
- exports 与 module.exports
- 为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。
var exports = module.exports;
- 于是我们可以直接在 exports 对象上添加方法,表示对外输出的接口,如同在module.exports 上添加一样。注意,不能直接将exports变量指向一个值,因为这样等于切断了exports与module.exports的联系。
ES6
- 不同于CommonJS,ES6使用 export 和 import 来导出、导入模块。
1 | // profile.js |
- 需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
1 | // 写法一 |
export default
- 使用export default命令,为模块指定默认输出。
1 | // export-default.js |
fs
- 文件系统模块,负责读写文件
- 和所有其它JavaScript模块不同的是,
fs
模块同时提供了异步和同步的方法。 - 参考
异步读文件
1 | fs.readFile('sample.txt', 'utf-8', function (err, data) { |
- 异步读取时,传入的回调函数接收两个参数,当正常读取时,
err
参数为null
,data
参数为读取到的String。当读取发生错误时,err
参数代表一个错误对象,data
为undefined
。 - 这也是Node.js标准的回调函数:第一个参数代表错误信息,第二个参数代表结果。后面我们还会经常编写这种回调函数。
读取图片
1 | fs.readFile('sample.png', function (err, data) { |
- 当读取二进制文件时,不传入文件编码时,回调函数的
data
参数将返回一个Buffer
对象。在Node.js中,Buffer
对象就是一个包含零个或任意个字节的数组(注意和Array不同)。Buffer
对象可以和String作转换,例如,把一个Buffer
对象转换成String:
1 | // Buffer -> String |
- 或者把一个String转换成
Buffer
:
1 | // String -> Buffer |
同步读文件
- 同步读取的函数和异步函数相比,多了一个
Sync
后缀,并且不接收回调函数,函数直接返回结果。
1 | var fs = require('fs'); |
- 如果同步读取文件发生错误,则需要用
try...catch
捕获该错误:
1 | try { |
path
path
模块的默认操作会因 Node.js 应用程序运行所在的操作系统而异。 具体来说,当在 Windows 操作系统上运行时, path
模块会假定正被使用的是 Windows 风格的路径。
path.dirname()
path.join([…paths])
path.join()
方法会将所有给定的 path
片段连接到一起(使用平台特定的分隔符作为定界符),然后规范化生成的路径。
1 | const path = require('path'); |
- 参数
- **[…paths]**:路径片段的序列。
- 返回:string
- 如果任何的路径片段不是字符串,则抛出
TypeError
。 - 长度为零的
path
片段会被忽略。 如果连接后的路径字符串为长度为零的字符串,则返回'.'
,表示当前工作目录。
path.resolve([…paths])
path.resolve()
方法会将路径或路径片段的序列解析为绝对路径。
给定的路径序列会从右到左进行处理,后面的每个 path
会被追加到前面,直到构造出绝对路径。
- 例如,给定的路径片段序列:[/目录1、/目录2、目录3],调用
path.resolve('/目录1', '/目录2', '目录3')
会返回/目录2/目录3
,因为'目录3'
不是绝对路径,但'/目录2' + '/' + '目录3'
是。
1 | const path = require('path'); |
- 参数:
- **[…paths]**:路径片段的序列。
- 返回:string
- 如果在处理完所有给定的
path
片段之后还未生成绝对路径,则会使用当前工作目录。 - 生成的路径会被规范化,并且尾部的斜杠会被删除(除非路径被解析为根目录)。
- 零长度的
path
片段会被忽略。 - 如果没有传入
path
片段,则path.resolve()
会返回当前工作目录的绝对路径。
path.relate(from, to)
path.relative()
方法根据当前工作目录返回 from
到 to
的相对路径。
如果
from
和to
各自解析到相同的路径(分别调用path.resolve()
之后),则返回零长度的字符串。如果将零长度的字符串传入
from
或to
,则使用当前工作目录代替该零长度的字符串。
1 | /* POSIX上 */ |
- 参数:
- from:string
- to:string
- 返回:string
- 如果
from
或to
不是字符串,则抛出TypeError
。
stream
http
1 | // 导入http模块: |
request
:封装了HTTP请求,我们调用request
对象的属性和方法就可以拿到所有HTTP请求的信息;- {‘Content-Type’: ‘text/html’}:设置类型为html页面
- 方法
req.on('data', function(data){})
:data为一个buffer数据,需要将所有数据包的字节都存储起来,再来分析req.on('end', function(data){ res.end(); })
:在出发结束的函数后,再在他的function里面结束相应res.end();
response
:封装了HTTP响应,我们操作response
对象的方法,就可以把HTTP响应返回给浏览器。- 方法
response.writeHead()
:设置http协议头,给浏览器看的response.write()
:仅发送数据response.end()
:发送并结束请求,必须有,可以发送空
- 方法
编码模式
- 浏览器默认
urlencode
字符集编码,不支持中文- 接收浏览器的请求数据res,在nodejs中输出是中文适配的
- 但是如果直接将中文传到浏览器输出将会出现乱码,所以设置html页面属性meta为
utf-8
1 | res.write('<head><meta charset="utf-8"/></head>'); |
请求内容
- GET:
- 由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET请求的参数。
- 下面 url 模块中的
parse
函数提供了这个功能。
- POST:
- POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。
- 比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所以 node.js 默认是不会解析请求体的,当你需要的时候,需要手动来做。
- 下面的querystring和util模块提供了相应的处理
url
1 | var url = require('url'); |
querystring
模块提供用于解析和格式化 URL 查询字符串的实用工具
1 | var querystring = require('querystring'); |
序列化:url -> 对象
querystring.parse(str[, sep[, eq[, options]]])
把一个URL查询字符串(str)解析成一个键值对的集合
参数
str:要解析的 URL 查询字符串
sep:用于在查询字符串中分隔键值对的子字符串。默认值:
'&'
eq:用于在查询字符串中分隔键和值的子字符串。默认值:
'='
。Options:
decodeURIComponent
当解码查询字符串中的百分比编码字符时使用的函数。默认值: querystring.unescape()
。maxKeys
指定要解析的键的最大数量。指定 0
可移除键的计数限制。默认值:1000
。- 注:默认情况下,会假定查询字符串中的百分比编码字符使用 UTF-8 编码。 如果使用其他的字符编码,则需要指定其他的
decodeURIComponent
选项
1
2
3
4
5
6var str = "foo=bar&abc=xyz&abc=123"
var body = querystring.parse(str)
//body = '{ foo: 'bar', abc: [ 'xyz', '123' ] }'
querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,
{ decodeURIComponent: gbkDecodeURIComponent });
注意:本方法返回的对象不继承自 JavaScript 的 Object。 这意味着典型的 Object 方法如
obj.toString()
、obj.hasOwnProperty()
等没有被定义且无法使用
反序列化:对象 -> url
querystring.stringify(obj[, sep][, eq][, options])
通过遍历对象的自有属性,从一个给定的obj产生一个URL查询字符串
参数:
obj:要序列化为 URL 查询字符串的对象。
sep:用于在查询字符串中分隔键值对的子字符串。默认值:
'&'
eq:用于在查询字符串中分隔键和值的子字符串。默认值:
'='
options:
1
2
3
4
5querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// 返回 'foo=bar&baz=qux&baz=quux&corge='
querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// 返回 'foo:bar;baz:qux'
编码
querystring.escape(str)
querystring.unescape(str)
给定的
str
上执行 URL 百分比编码字符的解码querystring.unescape()
方法由querystring.parse()
使用,通常不会被直接地使用。 它的导出主要是为了允许应用程序代码在需要时通过将querystring.unescape
赋值给替代函数来提供替换的解码实现。默认情况下,
querystring.unescape()
方法将会尝试使用 JavaScript 内置的decodeURIComponent()
方法进行解码。 如果失败,则将会使用更保险的不会因格式错误的 URL 而抛出异常的同类方法。
body-parser
socket.io
crypto
crypto.createHash(algorithm, key[, options])
node-rsa
密钥格式:
密钥内容标准规范:PKCS(The Public-Key Cryptography Standards)
- 由美国RSA公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。
- 版本:现有PCKS1,PCKS3,PCKS5,PKCS6,PKCS7,PKCS8,PKCS9,PKCS10,PKCS11,PKCS12,PKCS13,PKCS14,PKCS15 共 13个版本
常用:PCKS1 和 PCKS8,本文使用 PCKS8 标准
密钥展示与传输格式
DER:基于二进制的编码。可以用CER或者CRT作为扩展名的的整数。比较合适的说法是“我有一个DER编码的证书”,而不是“我有一个DER证书”。
PEM:基于ASCII(Base64)的编码。OpenSSL 使用 PEM 文件格式存储证书和密钥。
实质上是 base64 编码的二进制内容,再进行增加或裁剪特殊字符-、\n、\r、begin信息、end信息等,如:
-----BEGIN CERTIFICATE----- 内容 -----END CERTIFICATE-----
1
2
3
4
5
6
7
8
9
10
11
12
*
```javascript
var NodeRSA = require('node-rsa');
const key = new NodeRSA([keyData, [format]], [options]);
keyData { string|buffer|object }:用于生成密钥或所支持格式之一的密钥的参数。
format { string }:导入密钥的格式。
options { object }:其他设置。
导入导出密钥
key.importKey(keyData, [format]);
key.exportKey([format]);
1 | var key = new NodeRSA({b: 512}); //生成512位秘钥 |
- format:指定rsa算法标准
pkcs8-public
、pkcs1-public-pem
加密解密
- default:
- 公钥加密
key.encrypt(buffer, [encoding], [source_encoding]);
<==> - 私钥解密
key.decrypt(buffer, [encoding]);
- 公钥加密
- extend:
- 私钥加密
key.encryptPrivate(buffer, [encoding], [source_encoding]);
<==> - 公钥解密
key.decryptPublic(buffer, [encoding]);
- 私钥加密
1 | /* 使用公钥对 buffer 进行加密 */ |
- 一般默认使用公钥加密,用私钥来解密,所以内置了
encrypt
和decrypt
函数
1 | /* 使用私钥对 buffer 进行加密 */ |
- 但也可以像上面这样反过来,使用
encryptPrivate
的私钥加密,和decryptPublic
的公钥解密
签名验证
key.sign(buffer, [encoding], [source_encoding]);
key.verify(buffer, signature, [source_encoding], [signature_encoding])
1 | /* 私钥签名*/ |
- buffer:
{buffer}
— 用于检查的数据,与encrypt
方法相同。 - signature:
{string}
— 检查的签名,sign
方法的结果。 - source_encoding:
{string}
— 与encrypt
method相同。 - signature_encoding:
{string}
— 给定签名的编码。可能是'buffer'
,'binary'
,'hex'
或'base64'
。默认为'buffer'
.
其他
1 | var priKey = new NodeRSA(privateKey,'pkcs8-private'); |
isPrivate()
:判断是否是私钥,是的话返回 trueisPublic([strict])
:判断是否是公钥strict
只在私钥是有效:为 false 时(默认),与判断私钥相同,为 true 时才判断是否为公钥。
时间
Date()
1 | const time = new Date(); |
silly-datetime
1 | var sd = require('silly-datetime'); |
moment
- 日期格式化
1 | const moment = require('moment'); |
- 相对时间
1 | /* 当前时间 */ |
- 日历时
1 | /* 当前时间 */ |
其他更多的函数参考:http://momentjs.cn/docs/
- 示例
计算俩日期相差多少天
1 | // 获取当前时间 |
当前日期往后加几天
1 | moment().add(30, "days").format('YYYY-MM-DD HH:mm:ss') |
指定日期往后加几天
1 | moment("传入时间戳").add(30, "days").format('YYYY-MM-DD HH:mm:ss') |
- clone
所有的 moment 都是可变的。 如果想要克隆 moment,则可以隐式或显式地操作。
在 moment 上调用 moment() 将会克隆它。
1 | var a = moment([2012]); |
同步异步
async-await
Async/await的主要益处是可以避免回调地狱(callback hell),且以最接近同步代码的方式编写异步代码。
基本概念
- promise 对象:
- 有三种状态:成功(Fulfilled)、失败(Rejected)、等待(Pending)
- 不配合<async, await>时,使用
.then()
和.catch()
处理成功和失败情况是目前的常规方案。
- async 表示这是一个async函数,await只能用在这个函数里面。async 对象也是一个 promise 对象。
- await 表示在这里等待 promise 返回结果了,再继续执行。
- await 后面跟着的应该是一个 promise 对象(当然,其他返回值也没关系,不过那样就没有意义了…)
- 很多库的接口返回 promise 对象,await 后赋值给一个变量后使用其 resolve 的值。例如
- 注意三点,promise 对象的状态,promise 对象上的方法(then,catch),promise 对象返回的值。
- promise 是当时为了解决回调地狱的解决方案,也是当前处理异步操作最流行和广泛使用的方案,async 和 await 最为当前的终极方案两只之间还有一些过渡方案。
示例:
1 | var showArticle = async function () { |
Promise
实现延时
https://zhuanlan.zhihu.com/p/163292394
- 使用
setTimeout
函数
1 | function wait(ms) { |
- 使用for和
Date
1 | // 函数实现,参数 delay 单位 毫秒 ; |
- 在nodejs平台调用Linux系统自带的
sleep
函数
1 | // 函数实现,参数单位 秒 ; |
框架
express
- 基于nodejs平台的web应用开发框架
- https://www.cnblogs.com/yiliweichinasoft/p/3851791.html
server.js
1 | const express = require('express'); |
router/login.js
1 | const express = require('express'); |
- 当用户访问:
/user/gainover/edit
时,首先会调用第一个处理函数loadUser,判断用户是否存在于users中,如果不存在,通过next(new Error(msg));
的方式抛出异常,否则,执行next(),而next此时实际就是指向 andRestrictToSelf 函数,然后判断当前登录的id和被编辑的id是否等同,如果等同,则继续next()
,从而执行res.send( ...);
koa
Fabric
(指路fabric篇)
实例
多人实时聊天服务器
HTTP
Socket
npm install socket.io --save
网络上的程序实现双向的数据链接,这个链接的一端成为socket。
1.Socket是一个持久链接。
2.Socket是双向通信的。
Socket VS ajax轮询
- ajax轮询 , 是利用客户端来发送请求,每隔几秒发送一个http请求,服务器压力大。
- Socket不会,一旦链接不会断开,可以实现实时通信。 比如微信的朋友圈更新提示。即时聊天通讯。
p2p
- Post title:nodejs
- Post author:Wei Jieyang
- Create time:2020-12-18 17:56:37
- Post link:https://jieyang-wei.github.io/2020/12/18/nodejs/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.