nodejs

202 阅读5分钟

1、学习nodejs能干嘛

可以操作网络、硬盘、内存、摄像头、数据库等等,不局限浏览器
(浏览器有引擎解析 ecmascript, nodejs也是基于ecmascript,需要v8引擎来解析)

2、mac 上node的安装路劲
node的安装路劲 mac上一般都是 /usr/local/bin 下面

3、mac 上node的运行环境 cli+repl
cli(命令行) repl (read eval print loop 读、执行、打印、循环继续监听)

repl命令:
.break
.clear
.exit
.help
.save
.load
.editor


4、global 全局对象
__dirname 当前所在目录
__filename 当前文件所在绝对路劲及文件名


4-1、event loop 事件循环

  • event loop会先执行主线任务,在执行异步任务(异步任务包括timer定时器和i/o ajax类异步任务)
先执行宏任务,再执行微任务
执行顺序: 主线任务》异步任务》宏任务》微任务

  • event loop 宏任务
主体script, setTimeout,setInterval
  • event loop 微任务
promise.then (new promise 是宏任务,promise的对象的then是微任务), process.nextTick

案例

所以以下代码会执行打印a,c,b
```
console.log('a')
setTimeout(function(){
console.log('b')
})
console.log('c')
```

阶段预览:
timers:执行setTimeout()和setInterval安排的回调
I/O callbacks: 执行几乎所有异常的close回调,由timer和setImmediate执行的回调。
idle,prepare: 只用于内部
poll : 获取新的I/O事件,node在该阶段会适当的阻塞
check : setImmediate的回调被调用
close callbacks: e.g socket.on('close',…);
在每次运行事件循环之间,node.j检查是否有正在等待的异步i/o调用、timers等。如果没有,就清除并结束(退出程序),例如:执行一个程序,仅有一句话(var a= ‘hello’;),处理完目标代码后,不会进入evetloop,而是直接结束程序。

参考链接

5、Modules 模块化 (内置模块)
模块化的定义: 一个文件就是一个模块
导入: require('./xxx.js') ( 会接收一个返回值,exports到出的值/对象)
导出: module.exports (exports 是 module.exports 的简写)

exports 和module.exports的区别
exports 可以到出基本类型, 适合单个导出
module.exports 既可导出基本类型、又可导出引用类型对象, 适合批量导出

代码解释:
```
var module = {
exports: {
}
}

var exports = module.exports

他们相当于这个引用关系;
如果:exports = {a:1}; 此时 exports 和module.exports 就断开了引用关系,所以exports 直接批量导出一个对象会有问题
```

模块化分类
  • file modues
  • folders as modules
    • node_modules folders
    • global folders
  • core modules

在文件夹下可以新建package.json 用main指定默认加载的js名字
如一下package.json, 会默认识别main.js 而不是index.js
```
{
"name" : "test",
"main" : "./mian.js"
}
```


模块化加载机制
  • 路劲加载模式
    • /
    • ./
    • ../

  • 非路劲加载模式
    • node_modules
    • 全局目录 (系统盘符-》用户文件夹-》全局的node_modules)
    • 核心模块

例子,如果在 '/home/ry/projects/foo.js' 文件里调用了 require('bar.js'),则 Node.js 会按以下顺序查找:
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
这使得程序本地化它们的依赖,避免它们产生冲突

模块加载后缀机制
文件>.js>.json>.node

console内置模块
timers内置模块
Event 事件触发器内置模块
类似于js的 addEventListenner
```
const EventEmmiter = require('events');
const myEmitter = new EventEmmiter();

// 监听事件方式1
// myEmitter.on('event', (a, b) => {
// console.log(a, b, this);
// // 打印: a b {}
// });

// 监听事件方式2
myEmitter.addListener('event', function(a,b) {
this.defaultMaxListeners = 2
console.log(this)
console.log(this.getMaxListeners())
})

myEmitter.emit('event', '10', 'b111');
```



Process内置模块
全局对象,不需要require引入
  • process.argv // 当前node运行环境对应的参数
```
let api = '';
if(process.argv.includes('prod')){
api = 'http://prod.xx.com'
}else if(process.argv.includes('test')){
api = 'http://test.xx.com'
}else if(process.argv.includes('dev')){
api = 'http://dev.xx.com'
}
console.log(api)

然后node命令执行: node test.js prod // 结果输出 http://prod.xx.com
```
  • process.env
命令行可以 执行set 查看环境变量;
关于各个系统对环境变量的设置 www.cnblogs.com/fhen/p/6293…
win系统:
#node中常用的到的环境变量是NODE_ENV,首先查看是否存在
set NODE_ENV
#如果不存在则添加环境变量
set NODE_ENV=production
#环境变量追加值
set 变量名=%变量名%;变量内容
set path=%path%;C:\web;C:\Tools
#某些时候需要删除环境变量
set NODE_ENV=
mac系统
#node中常用的到的环境变量是NODE_ENV,首先查看是否存在
echo $NODE_ENV
#如果不存在则添加环境变量
export NODE_ENV=production
#环境变量追加值
export PATH=$PATH:/home/download:/usr/local/
#某些时候需要删除环境变量
unset NODE_ENV
#某些时候需要显示所有的环境变量
env
linux系统
#node中常用的到的环境变量是NODE_ENV,首先查看是否存在
echo $NODE_ENV
#如果不存在则添加环境变量
export NODE_ENV=production
#环境变量追加值
export path=$path:/home/download:/usr/local/
#某些时候需要删除环境变量
unset NODE_ENV
#某些时候需要显示所有的环境变量
env

案例代码:
```
let config = {
'dev': {
api: 'http://dev.xxx.com/'
},
'test': {
api: 'http://test.xxx.com/'
},
'prod': {
api: 'http://prod.xxx.com/'
},
}
let api = config(process.env.mode).api
console.log(api)
```
  • process.exit([code]) // 结束当前进程
```
let i = 0;
setInterval( ()=>{
i++;
console.log(i);

if(i>=3){
process.exit(1)
}
}, 100)
// 结果输出 1 2 3
```
  • process.stdout 标准输出流
类似于 console.log('xxx')
  • process.stdin 标准输入流

案例:做一个类似 vue-cli3 的命令行创建项目
```
var fs = require('fs');
process.stdout.write('请输入要创建的文件夹英文名称:');

process.stdin.on('data', (e) => {
// e 是buffer数据
let folderName = e.toString().trim();
fs.mkdirSync(folderName)

process.stdout.write('文件创建成功');
})
```



Stream 流
流的概念比较抽象,具体实现有具体的类实现
流的基本类型
  • stream.writable 可写入数据的流 如:fs.createWriteStream()
常用属性方法:
    • write(chunk[,encoding][,callback])
    • end(chunk[,encoding][,callback])
    • setDefaultEncoding(encoding)
  • stream.Readable 可读取数据的流 如:fs.createStream()
常用属性方法:
  • readable.setEncoding(encoding)
  • readable.read([size])
  • readable.pipe(destination[, options])
  • readable.pause()
  • readable.resume()
  • stream.Duplex 可读可写的流(双工数据流) 如:net.Socket()
  • stream.Transform 在读写过程中可修改或可转换数据流(可修改的双工数据流) 如:zlib.createDealate()
Buffer 二进制数据类 (34)
用户操作二进制数据的类;也是全局变量,无需require引入
基本特性
  • 类似数组
  • 长度固定
  • 只能操作二进制数据



FileSysterm

Npm

第三方模块