一、是什么:是一个JavaScript运行环境,使用事件驱动,非阻塞I/O的模型
1、非阻塞I/O
阻塞I/O:I/O时进程休眠等待I/O完成后进行下一步
非阻塞I/O:I/O时函数立即返回,进程不等待I/O完成
2、事件驱动:I/O等异步操作结束后的通知
二、基础api
1、path
// 标准化
const {normalize} = require('path');
// == const normalize = require('path').nomalize;
console.log(normalize('/user//local/bin'));
console.log(normalize('user/local/../bin'));
// 合并路径,也会调用normalize对路径标准化
const {join} = require('path');
console.log(join('/user', '//local', 'bin//'));
// 将相对路径转化为绝对路径
const {resolve} = require('path');
console.log(resolve('./'));
// 文件路径操作
const {basename, dirname, extname} = require('path');
const filepath = '/user/local/bin/no.txt';
console.log(basename(filepath)); // 文件名
console.log(dirname(filepath)); // 目录名
console.log(extname(filepath)); // 文件名后缀
// 解析路径
const {parse, format} = require('path');
const filepath1 = '/user/local/bin/11.txt';
const res = parse(filepath1); // 将路径解析为对象
console.log(res);
console.log(format(res)); // 将对象解析为路径,和parse相反
// __filename,__dirname总是返回文件的绝对路径
console.log('__filename', __filename);
console.log('__dirname', __dirname);
// process.cwd()返回node命令所在的文件夹
console.log('__process', process.cwd());
2、buffer:处理二进制数据流,为全局变量
console.log(Buffer.alloc(10)); // 生成长度为0,用0填充的Buffer
console.log(Buffer.alloc(5, 2)); // 生成长度为5,用2填充的Buffer
console.log(Buffer.allocUnsafe(5, 1)); // 生成长度为5,未初始化的,生成空间,随机的值
console.log(Buffer.from([1, 2, 3])); // 从1,2,3 中选取数据
console.log(Buffer.from('test')); // 会转换为ASCII码
console.log(Buffer.from('test', 'base64')); // 会转换为base64
// 结果
<Buffer 00 00 00 00 00 00 00 00 00 00>
<Buffer 02 02 02 02 02>
<Buffer a8 1b 17 5d 3f>
<Buffer 01 02 03>
<Buffer 74 65 73 74>
<Buffer b5 eb 2d>
console.log(Buffer.byteLength('test')); // 占的字节长度
console.log(Buffer.byteLength('测试')); // 中文3个字节
console.log(Buffer.isBuffer({})); // 某个对象是buffer对象吗
console.log(Buffer.isBuffer(Buffer.from([1, 2, 3])));
const buf1 = Buffer.from('this ');
const buf2 = Buffer.from('is');
const buf3 = Buffer.from('a');
// 合并buffer,一个参数,多个参数为数组
const buf = Buffer.concat([buf1, buf2, buf3]);
console.log(buf, buf.toString());
// 结果
4
6
false
true
<Buffer 74 68 69 73 20 69 73 61> 'this isa'
const buf5 = Buffer.allocUnsafe(10); // 生成空间为10的buffer,
console.log(buf5.fill(10, 2, 6)); // 填充10,从2开始到6,包括2不包括6
const buf6 = Buffer.from('test');
const buf7 = Buffer.from('test');
console.log(buf6.equals(buf7)); // 判断是否同一个buffer
console.log(buf6.indexOf('t')); // 如果有返回索引,没有==-1
const b = Buffer.allocUnsafe(4);
buf6.copy(b, 0, 2); // 把buf6的0-2的值给b,不包括2
console.log(b);
// 结果
<Buffer 00 3a 0a 0a 0a 0a 00 00 28 f2>
true
0
<Buffer 73 74 00 00>
3、event:事件
const EventEmitter = require('events'); // 引入
class MyEvent extends EventEmitter { // 定义自己的事件
}
const ev = new MyEvent(); // 实例化
ev.on('test', function () { // 绑定事件
console.log(11);
});
setInterval(function () {
ev.emit('test'); // 触发
}, 1000);
传参:
ev.on('text', (err, time) => { // 接收参数
console.log(err);
console.log(time);
});
ev.emit('text', new Error('this is a error'), Date.now()); // 当传参时
ev.once('text1', () => { // 只会执行一次
console.log(11);
});
setInterval(() => {
ev.emit('text1');
}, 1000);
事件移除
function fn1 ()
{
console.log('fn1');
}
function fn2 ()
{
console.log('fn2');
}
const ev = new MyEvent();
ev.on('text', fn1);
ev.on('text', fn2);
setInterval(() => {
ev.emit('text');
}, 500);
setTimeout(() => {
ev.removeListener('text', fn1); // 事件移除,事件名和事件内容
}, 1500);
ev.removeAllListeners('text'); // 移除所有的事件
4、fs的用法
const fs = require('fs');
// 异步用法:最后一个为回调,最好都有异常判断
fs.readFile('./event.js', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 同步用法:先执行
const data = fs.readFileSync('./event2.js', 'utf8');
console.log(data);
写入文件:const fs = require('fs');
// 文件、内容、编码(默认utf8)、回调
fs.writeFile('./text1', 'this is a text!', 'utf8', (err) => {
if (err) throw err;
console.log('done');
});
查看文件状态
const fs = require('fs');
// 查看文件状态
fs.stat('./text1', (err, stats) => {
// 判断文件是否存在
if (err) {
console.log('文件不存在');
return;
}
console.log(stats.isFile()); // 判断是文件吗
console.log(stats.isDirectory());
});
删除文件
const fs = require('fs');
fs.unlink('./text.txt', err => { // 删除文件
if (err) throw err;
console.log('unlink');
});
重命名
const fs = require('fs');
fs.rename('./text1', 'text.txt', err => { // 旧的,新的
if (err) throw err;
console.log('done');
});
目录读取,新建
const fs = require('fs');
fs.readdir('./', (err, files) => { // 读取目录,当前目录
if (err) throw err;
console.log(files);
});
fs.mkdir('test', err => { // 新建一个目录
if (err) throw err;
console.log('test');
});
文件监听
const fs = require('fs');
fs.watch('./', {
recursive: true // 是否递归,包括子文件
}, (type, filename) => {
console.log(type, filename); // 改变的文件事件,和文件名
});
5、http的使用
(1)小练习
const http = require('http'); // 引入http模块
const chalk = require('chalk'); // 关于颜色的插件,可以改变文本颜色
const conf = require('./config/defaultConfig.js'); // 引入配置中的变量
const server = http.createServer((req, res) => { // 第一步要创建一个服务,请求,响应
res.statusCode = 200; // 响应码
res.setHeader('Content-type', 'text-plain'); // 响应头
res.end('hello http'); // 完成后会输出在页面上
});
server.listen(conf.port, conf.hostname, () => { // 给服务加监听
const addr = 'http://'+conf.hostname + ':' + conf.port;
console.log('server started at ' + chalk.green(addr));
})
defaultConfig.js中
module.exports = {
hostname: '127.0.0.1',
port: '3000'
}
(2)、每次修改时,都要重启服务,可以使用supervisor来执行,修改内容后,只要刷新就行了
npm install -g supervisor // 全局安装
执行:
supervisor server.js // 不在使用node server.js
(3)、文件资源管理器
const http = require('http'); // 引入http模块
const chalk = require('chalk'); // 关于颜色的插件,可以改变文本颜色
const path = require('path');
const fs = require('fs');
const conf = require('./config/defaultConfig.js'); // 引入配置中的变量
const root = process.cwd(); // node运行时的命令所在目录
const server = http.createServer((req, res) => { // 第一步要创建一个服务,请求,响应
const filePath = path.join(root, req.url); // url为端口号后面的路径
console.log(filePath);
fs.stat(filePath, (err, stats) => { // 查看文件状态
if (err) { // 文件不存在
res.statusCode = 404; // 响应码
res.setHeader('Content-type', 'text-plain'); // 响应头
res.end(filePath + 'is not a director or file');
return;
}
if (stats.isFile()) { // 如果是文件读取,
res.statusCode = 200; // 响应码
res.setHeader('Content-type', 'text-plain'); // 响应头
fs.createReadStream(filePath).pipe(res); // 以流的方式读取文件,并吐给res
} else if (stats.isDirectory()) { // 如果是目录,打开
fs.readdir(filePath, (err, files) => {
res.statusCode = 200; // 响应码
res.setHeader('Content-type', 'text-plain'); // 响应头
res.end(files.join(','));
})
}
});
});
server.listen(conf.port, conf.hostname, () => { // 给服务加监听
const addr = 'http://'+conf.hostname + ':' + conf.port;
console.log('server started at ' + chalk.green(addr));
})