node-event-fs-stream-router-async
事件event模块
使用事件:EventEmitter 事件的参数 只执行一个的事件监听器
Node.js核心API的大部分是围绕一个惯用的异步事件驱动架构构建的,其中某些类型的对象(称为“发射器”)周期性地发出命名事件,导致调用Function对象(“侦听器”)
const EventEmmiter = require('events')
class myEmmiter extends EventEmmiter {}
const evt = new myEmmiter()
// evt.on('play', function (name) {
// console.log(name)
// })
const callback = (name) => {
console.log(name)
}
evt.on('play', callback)
// evt.removeListener('play', callback)
evt.emit('play', '结爱')
evt.emit('play', '黄皮子坟')
1.fs文件基本操作
1.1 简介:
Node.js 的 fs 是一个类似标准 POSIX 函数的用来操作文件的模块,它对所有的文件系统操作都有异步 和同步两种形式。不过,需要注意的是“当采用异步形式的时候,回调函数的第一个参数都会保留给异常,如果 操作成功完成,则第一个参数会是 null 或 undefined”
1.2.fs 模块引入及基本用法:
const fs = require('fs');
//异步的方式
fs.readFile('./test.js', (err, data) => {//handle })
const data = fs.readFileSync('./test.js'); //同步的方式
1.3.fs.open(path, flags[, mode], callback) 异步的方式打开文件
fs.open 方法通常用来打开一个文件地址、URL 或者 Buffer。
其中 flags 参数可以是:
r - 以读取模式打开文件。如果文件不存在则发生异常。
r+ - 以读写模式打开文件。如果文件不存在则发生异常。
rs+ - 以同步读写模式打开文件。命令操作系统绕过本地文件系统缓存。
使用:
const fs = require('fs');
fs.open('./public/test.js', 'rs+', (err, fd) => {
if(err) { console.log('文件打开失败!'); return false;
}
fs.write(fd, ...) //在这里可以对上述打开的文件进行一系列的操作 })
1.4如果您想采用同步的方式来操作,则应该使用 fs.openSync()。
const fs = require('fs');
const fd = fs.openSync('./public/test.js', 'rs+');
1.5 fs.readFile(path[, options], callback) 异步的方式读取文件
fs.readFile 方法可以用来读取一个文件的具体内容
const fs = require(‘fs’);
fs.readFile(’./test.js’, ‘utf-8’, (err, data) => { if (err) throw err; console.log(data);//这里将输出test.js的具体内容
})
注意:
如果您需要使用同步的方式来读取文件,可以使用 fs.readFileSync 方法来实现。
由于 fs 模块对每一 个文件操作都提供了同步和异步两种操作方式,
这里以及下文都将只演示异步的方式(因为,方法的实现就差 一个回调函数)。
1.6 fs.write(fd, buffer[, offset[, length[, position]]], callback) 异步的方式写入文件
通过 fs.write 方法可以将字符串或者 Buffer 写入一个指定的文件(fd)
const fs = require('fs');
fs.open('./test.txt', 'rs+', (err, fd) => {
if(err) {
console.log('文件打开失败!');
return false;
}
fs.write(fd, 'hello world', (err, written, str) => {
if(err) throw err;
console.log(written); //11
console.log(str); //hello world
}) })
1.7 fs.close(fd, callback) 异步的方式关闭文件
与 fs.open 方法相反,fs.close 方法可以用来关闭一个已经打开的文件。例如:
const fs = require('fs');
fs.open('./public/test.js', 'rs+', (err, fd) => {
if (err) {
console.log('文件打开失败!');
return false;
}
//handle
fs.close(fd, err => {
if (err) throw err; //关闭文件的回调函数体
}) })
1.8 fs.unlink(path, callback) 异步的方式删除文件 fs.unlink 方法可以删除一个文件(不能删除目录)。例如:
const fs = require(‘fs’);
fs.unlink(’./test.txt’, err => { if (err) throw err; console.log(‘删除成功!’);
})
1.9 fs.readdir(path[, options], callback) 读取一个目录
当我们需要知道某个目录下都有那些文件或者文件夹的时候,我们可以使用 fs.readdir 方法来实现。例 如:
const fs = require('fs');
fs.readdir('./', (err, files) => {
if (err) throw err;
console.log(files.join(';')); //这里将输出当前路径下的所有文件、文件夹名称并通过“;”分隔
})
注意: fs 模块的每一个方法都提供了异步与同步的两种操作方式。其中,异步的方式性能高,是一种推 荐的操作方式。如果您需要采用同步的方式,只要在异步方法名后面加上 Sync 即可,同时去掉末尾的 callback 参数。
1.10 http模块创建服务器+fs文件操作+服务器监听
const http = require('http')
const fs = require('fs')
http.createServer((req, res) => {
res.writeHead(200, {
'content-type': 'text/html'
})
switch (req.url) {
case '/home':
fs.readFile('./views/home.html', 'utf8', (err, data) => {
res.end(data)
})
break;
case '/api/signin':
res.end('signin')
break;
case '/app.js':
fs.readFile('./app.js', 'utf8', (err, data) => {
res.end(data)
})
break;
case '/ajax-loader.gif':
fs.readFile('./ajax-loader.gif', (err, data) => {
res.end(data)
})
break;
default:
res.end('404')
}
}).listen(8000, 'localhost', () => {
console.log('server is running at localhost:8000');
})
2.stream流模块
2.1 fs流的简介
2.1.1 stream:流是一个抽象接口,有四种流类型:
readable:可读
writable:可写操作
duplex:可读可写操作
transform:操作被写入数据,然后读出结果
2.1.2 所有的stream 象都是EventEmitter 的 例,常用事件有:
data:当有数据可读触发
end:没有数据可读触发
error:发生错误时触发
finish:完成触发
2.2 fs.createReadStream(path[, options]) 创建一个可读流 fs.createReadStream 方法通常用来创建一个可读流。例如:
const fs = require('fs');
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('./public/test.js');
// 设置编码为 utf8。 readerStream.setEncoding('UTF8');
// 处理流事件 --> data, end, and error readerStream.on('data', function(chunk) {
data += chunk;
});
readerStream.on('end',function(){
console.log(data);
});
readerStream.on('error', function(err){
console.log(err.stack);
}); console.log("程序执行完毕");
2.3 fs.createWriteStream(path[, options]) 创建一个可写流
fs.createWriteStream 方法可以创建一个可写入流对象,通过这个对象可以将自己想要写入的信息写到指定文件。例如:
var fs = require("fs");
var data = '这是我要写入到test.js文件中的数据';
// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('./public/test.js');
// 使用 utf8 编码写入数据 writerStream.write(data, 'UTF8');
// 标记文件末尾 writerStream.end();
// 处理流事件 --> data, end, and error writerStream.on('finish', function () {
console.log("写入完成。"); });
writerStream.on('error', function (err) {
console.log(err.stack);
}); console.log("程序执行完毕");
2.4 readerStream.pipe(writerStream) 将可读流信息导入可写流(即管道流) readerStream.pipe 方法可以将我们创建的可读流文件信息一一导入到可写流当中。例如:
var fs = require("fs");
// 创建一个可读流
var readerStream = fs.createReadStream('input.txt');
// 创建一个可写流
var writerStream = fs.createWriteStream('output.txt');
// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中 readerStream.pipe(writerStream); console.log("程序执行完毕");
2.5 链式流
链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作。例如我们可 以用管道和链式来压缩和解压文件:
//压缩
var fs = require("fs");
var zlib = require('zlib');
// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz')); console.log("文件压缩完成。");
//解压
var fs = require("fs");
var zlib = require('zlib');
// 解压 input.txt.gz 文件为 input.txt fs.createReadStream('input.txt.gz')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt')); console.log("文件解压完成。");
3.路由+图片读取
总结:
1. 为什么要引进前端路由这样一个东西
2. 书写路由
3. js文件的读取
4. 图片的读取
5.css文件的读取
const http = require('http')
const fs = require('fs')
http.createServer((req, res) => {
res.writeHead(200, {
'content-type': 'text/html'
})
switch (req.url) {
case '/home':
fs.readFile('./views/home.html', 'utf8', (err, data) => {
res.end(data)
})
break;
case '/api/signin':
res.end('signin')
break;
case '/app.js':
fs.readFile('./app.js', 'utf8', (err, data) => {
res.end(data)
})
break;
case '/ajax-loader.gif’://图片读取
fs.readFile('./ajax-loader.gif', (err, data) => {
res.end(data)
})
break;
//如果你的图片和当前js不在同一级目录,这个时候我们必须去遍历目录,然后找到你要发送的那一个,然后再去读取文件,然后发送
case '/bd_logo1.png':
fs.readdir('./views',(err,data) => {
console.log( data ) ;
data.forEach( (item,index) => {
if(item == 'bd_logo1.png'){
fs.readFile(item,(err,data)=>{
res.end(data)
})
}
})
})
break;
default:
res.end('404')
}
}).listen(8000, 'localhost', () => {
console.log('server is running at localhost:8000');
})
4.异步流程相关(async)
-
Promise
https://blog.csdn.net/MrJavaweb/article/details/79475949 -
Async-await
-
Node.js 中的nextTick()和setimmediate()
https://www.cnblogs.com/5ishare/p/5268273.html
5.async库
https://caolan.github.io/async/
参考文档
Event-loop
http://www.ruanyifeng.com/blog/2014/10/event-loop.html?bsh_bid=983729729
史上最易读懂的 Promise/A+ 完全实现
https://zhuanlan.zhihu.com/p/21834559
4.1 promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1 resolved!')
}, 1000)
})
.then((result) => {
console.log(result);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2 resolved!')
}, 2000)
})
.then((result) => {
console.log(result);
})
// Promise.all([p1, p2])
// .then(() => {
// console.log('done.');
// })
Promise.race([p1, p2])
.then(() => {
console.log('done.');
})
4.2 generator
function* fibonacci() {
let [prev, curr] = [0, 1];
for (;;) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
for (let n of fibonacci()) {
if (n > 1000) break;
console.log(n);
}
4.3 async-await
const foo = function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('done.')
}, 1000)
})
}
const async = async () => {
console.log(await foo());
}
async()
4.4 nextTick()和setImmediate()
process.nextTick(function(){
console.log("nextTick延迟执行A");
});
process.nextTick(function(){
console.log("nextTick延迟执行B");
setImmediate(function(){
console.log("setImmediate延迟执行C");
});
process.nextTick(function(){
console.log("nextTick延迟执行D");
});
});
setImmediate(function(){
console.log("setImmediate延迟执行E");
process.nextTick(function(){
console.log("强势插入F");
});
setImmediate(function(){
console.log("setImmediate延迟执行G");
});
});
setImmediate(function(){
console.log("setImmediate延迟执行H");
process.nextTick(function(){
console.log("强势插入I");
});
process.nextTick(function(){
console.log("强势插入J");
});
setImmediate(function(){
console.log("setImmediate延迟执行K");
});
});
console.log("正常执行L");
4.5 async
串行无关联
async.series({
one: function(callback) {
setTimeout(function() {
callback(null, 1);
}, 200);
},
two: function(callback){
setTimeout(function() {
callback(null, 2);
}, 100);
}
}, function(err, results) {
console.log(results);
console.timeEnd('flag')
});
console.time('flag')
并行无关联
async.parallel({
one: function(callback) {
setTimeout(function() {
callback(null, 1);
}, 200);
},
two: function(callback){
setTimeout(function() {
callback(null, 2);
}, 100);
}
}, function(err, results) {
console.log(results);
console.timeEnd('flag')
});
串行有关联
async.waterfall([
function(callback) {
request.get('http://api.douban.com/v2/movie/in_theaters', (err, response, body) => {
if (!err) {
callback(null, JSON.parse(body));
} else {
console.log(err);
}
})
},
function(arg1, callback) {
let movies = arg1.subjects.map((value) => value.title)
let query = querystring.escape(`${movies[0]}`)
request.get(`http://api.douban.com/v2/movie/search?q=${query}`, (err, response, body) => {
if (!err) {
// console.log(JSON.parse(body));
callback(null, JSON.parse(body), 'three');
} else {
console.log(err);
}
})
},
function(arg1, arg2, callback) {
console.log(arg1);
callback(null, [arg1, arg2]);
}
], function (err, result) {
console.log(result);
console.timeEnd('flag')
});