Nodejs
全局对象
- `global`: 在nodejs中可以直接访问global对象,global中包括了process,__dirname,module等变量, 默认不加global也可以访问这些变量,global对应了前端的window对象
常用全局变量
- `__dirname`: 绝对路径
- `__filename`: 绝对路径
- `JSON`: `JSON.parse`解析
- `process`: 进程对象
- `env`
- `platform`
- `arch`
- `exit(0)`
- `stdin`
- `stdout`
- `console`: 控制台对象
- `console.log(msg, format)` 字符串格式化
- `%s`
- `%d`
- `%j`: 对象
常用全局函数
- `setTimeOut`: 返回timeID
- `clearTimeOut`
- `setInterval`: 返回timeID
- `clearInterval`
常见全局类
- Buffer
- 创建
- `var buf = Buffer.alloc(length)`
- `var buf = Buffer.from([1, 2, 3])`
- `var buf = Buffer.from('你好', 'utf8/base64')`: 第二个参数为编码
- 其他方法
- `buf.fill(0)`
- `buf.copy(src)`
- `buf.toString('base64/hex')`
- `buf.toString('hex', start, len)`
- `buf.readInt32LE(start)`: 从 start 位置读取 4 个字节
- 特性
- 本质上是一个字节数组,大小无法改变
模块导入与导出
- `const name = require('path')`
- `module.exports = {}`
事件模块
- 引入模块`const events = require('events')`
- EventEmitter类使用
- 创建对象`var emitter = new EventEmitter()`
- 监听事件`emitter.on('eventName', callback)`
- 发出事件`emitter.emit('eventName')`
- 同步的异常处理可以使用try-catch和throw
- 异步的异常处理通过事件解决, 发出异常的对象e.on('error', callback)监听error事件,发生error时,执行回调函数(类似try-catch),使用e.emit('error')发出异常事件(类似throw),注意都是在同一个对象上的。如果该对象没有监听error事件,这个时候发生了error,使用`process.on('uncaughtException', function(err){})`处理
流
- 模块: `process.stdin`和`process.stdout`
- 读取键盘: `process.stdin.resume()`,为异步操作
- 类: `Readable`和`Writeable`
fs模块
- `readFile`
- `writeFile`
监听文件或目录
- watch
Stream模块
- `ReadableStream`
- `WriteableStream`
util模块
- `util.inherits(subclass, superclass)`: 实现继承, 内部本质上是`subclass.prototype.__proto__ = superclass.prototype`
querystring模块
- Querystring.parse(params): 将username=abc&age=20处理成对象
解析URL
- `let url = new URL(url_string)`即可
http模块
- req和res对象
- req对象
- 属性
- Url
- Method
- hostname
- 方法
- Req.writeHead(statusCode, {字段})
- res对象
- 方法
- Res.write('content')
- Res.end()
- 对于post请求,分为头和内容,nodejs分两次处理,第一次调用时,req之后head信息,这个时候需要监听req.on('data', (params)=>{}), res.on('end', () => {}), 为之后req中填充数据再获取使用
mime模块
- 可以根据文件类型输出对应的响应文件类型(字符串)
Child_process模块
- Fork: 只用于node模块,并且父子进程是分离的
- `let child = cp.fork('path/to/module.js')`
- `child.on('message', function(message) {do something})` 这里是子进程处理js文件调用`process.send`触发的事件
- `child.send({})`向子进程发送数据
- 子进程js文件通过`process.on('message', function(message){})`处理父进程发送过来的数据, `process.send({})`发送给父进程数据
- 通过此模块可以实现web服务器每个请求对应一个进程
- Exec: 会创建一个subshell
- execFile: 子进程输出的结果保存在buffer中,通过回调函数处理
- Spawn: 子进程输出的结果保存在stream中
promise对象
- 构造方式是同步执行的
- 通过.then和.catch添加成功或者失败的回调函数
- 如果成功之后执行了resolve之后还想执行异步操作,return new Promise对象
第三方模块
- Gulp:类似webpack,建议使用webpack
router模块
- `router = getRouter()`
- `router.get('/path', (req, res) => {})` 在app.on的回调函数中`router(req, res, () => {})`
Serve-static模块
- 处理静态资源访问
- `serve(req, res, ()=>{})`在`app.on`的回调函数中调用
数据库使用
- mongoose操作mongodb
- 添加账号
- `mongo`
- `show dbs`
- `use db`
- 连接mongodb, `mongoose.connect('mongodb://localhost/database').then(()=>{}).catch((err)=>{})`
- 创建集合
- `const mySchema = new mongoose.Schema({name: String, classes: [String], age: Number})`
- `const My = mongoose.model('My', mySchema)`
- a和b两步分别创建集合结构,根据结构创建出集合类,'My'存储在数据库中是my
- `My`可以创建文档,save,delete
- 验证
- 创建集合时,构建集合规则这一步,传入字段时可以为字段设置属性, 如`field: {type: String, required: [true, 'error message'], minLength: [1, 'msg'], maxLength: [100, 'msg'], trim: true, min: 10, max: 20, default: defaultVal, enum: {values: [enum1, enum2], message: 'msg'}`其中default常用于日期,这个时候要传入Date.now函数对象
- 自定义验证规则
- `{filed: {validate: {validator: (value) => {}}}, message: 'write your msg'}`中validator函数返回true表示验证成功,返回false表示验证失败
- 集合关联
- 创建Schema时的字段,比如{name: {type: mongoose.schema.Types.ObjectId, ref: '另外一张表'}},这样就将这张表的name与另外一张表关联在一起的,在为当前表添加数据的时候,name传入的是另外一张表对应的id的字符串;而在查找时想将id字符串转为另外一张表中对应的对象,需要find({cond}).pupolate('name')即可
- 例如`Book.findOne().pupolate('author').then(result=>{})`此时的result表示的Book对象中的author原本为id字符串,经过populate转为了Author中对应id字符串的对象
- 增删改查
- 增:`Constructor.create(obj).then.catch`
- 删:
- `Constructor.findOneAndDelete(obj).then.catch` then中输入的参数为删除的文档
- `Constructor.deleteMany(obj).then.catch`
- 改
- `Constructor.updateOne({cond}, {更改的字段}).then.catch`
- `Constructor.updateMany({cond}, {更改的字段}).then.catch`
- 查`Constructor.find(obj).then.catch`, `Constructor.findOne(obj).then.catch`
- 表达式查询
- `Constructor.find({age: {$gt: 10, $lt: 20}}).then.catch`比较大小
- `Constructor.find(classNames: {$in: ['a', 'b']}).then.catch`表示包含
- 投影字段
- `Constructor.find().select('field1 field2 -field3').then.catch`表示投影出field1, field2但是不投影出-field3, field3常为_id
- 根据字段进行排序
- `Constructor.find().sort('age').then.catch`根据age进行升序
- `Constructor.find().sort('-age').then.catch`根据age进行降序
- 返回结构最大限制
- `constructor.find().limit(100).then.catch`常用于分页
- 导入数据库的工具
- `mongoimport -d database -c collection --file filepath`
- 模板引擎art-template使用
- `template(page_path, {obj})`
- 语法规则
- `{{ data }}`
- `{{ @data }}`如果data中包含html标签的话吗,否则默认引擎是不解析的
- 条件判断
- `{{ if cond }} … {{ /if }}`
- `{{ if cond }} … {{ else if cond }} … {{ /if }}`
- `{{ if cond }} … {{ else }} … {{ /if }}`
- 循环
- `{{ each list }} …{{ $index }} … {{ $value }} … {{ /each }}`
- 公共
- `{{ include 'path' }}`
- 继承
- `{{ block 'name'}} {{ /block }}`
- `{{ extend 'path' }}`
- 在模板中导入全局变量(也可以是函数)
- `template.defaults.imports.key = value`
- `template.defaults.root = path`
- `template.defaults.extname = name`
- 可在视图中的`{{ value(abc) }}`
- `bcrypt`模块加密
- `const bcrypt = require('bcrypt')`
- `bcrypt.genSalt(100)`生成随机数再使用`bcrypt.hash(str, 随机数)`进行加密
- 因为加密算法比较耗时,上述的API都是异步的
- `bcrypt.compare`对比
- `config`模块
- 切换开发,生产环境,根据NODE_ENV环境变量的值判断
- 使用
- 在项目目录下创建config目录,在此目录下创建development.json,production.json,custom-environtmen-variables.json和default.json文件,填写一些数据,比如数据库的配置,如果数据库的密码比较敏感,可以配置到环境变量中,通过custom-environment-variables.json进行配置,来引用该环境变量即可
- node作为服务器,想向其他服务器请求数据,使用`request`第三方模块