一.认识NodeJs
1.NodeJs的事件驱动和异步IO
1.在用户代码层,只启动一个线程来运行用户的代码;
2.耗时操作(比如文件读写/网络请求/数据库读写)交给底层的事件去执行,自己不会等待,继续执行下面的代码,当底层事件循环执行完耗时IO时,会执行其回调函数来作为通知;
缺点:
1.由于只有一个线程用来执行用户代码,如果耗时的是CPU计算操作,那么在循环过程中,下面的代码将会无法执行,阻塞了唯一的一个线程,因此,Node不适合大并发的IO处理,也不适合CPU密集型的计算操作.
2.npm介绍:
是nodejs自带的包管理器,类似maven仓库.官网:https://www.npmjs.com/;可以从官网上找第三方包.同时npm也方便了项目的迁移;
3.全局变量 global
全局变量是指在任何js文件的任何地方都可以使用的变量
__dirname:当前文件对的目录;
__filename:当前文件的绝对路径;
console:控制台对象,可以输出信息;
process:进程对象,可以获取进程的相关信息,环境变量等;
setTimeout/clearTimeout:延时执行
setInterval/clearUInterval:定时器
console.log(global.process)
console.log(global.process.env)
//env:环境变量
console.time("记录执行时间")
process.env.aaa = 'bbb';
console.log(process.env);
//错误级别
console.error("error级别的log");
console.log(__dirname);//E:\WorkSpace\Node\MyNode01
console.log(__filename);//E:\WorkSpace\Node\MyNode01\06_global-demo.js
//定时执行,执行一次
setTimeout(()=>{
console.log("执行了setout")
},10000);
console.timeEnd("记录执行时间");//3.390ms
//定时执行,一直执行
setInterval(()=>{
console.log("执行了setInterval")
},1000);
4.path模块
用于处理文件与目录的路径
path.basename:返回一个路径的最后一部分
path.dirname:返回一个路径的目录名
path.extname:返回一个路径的扩展名
pth.join:用于拼接给定路径片段
path.normalize:将一个路径正常化
//路径相关处理
let path = require('path');
console.log(__filename)//E:\WorkSpace\Node\MyNode01\07_path-demo.js
console.log(path.basename(__filename));//07_path-demo.js
console.log(path.dirname(__filename))//E:\WorkSpace\Node\MyNode01
console.log(path.extname(__filename))//.js
console.log(path.join("F:/x","y","z","a.txt"))//F:\x\y\z\a.txt
//把不正常的路径转换为正常的路径
console.log(path.normalize("f:/x\\y\\d/z"))//f:\x\y\d\z
5.fs模块
文件操作相关的模块
fs.stat/fs.statSync:访问文件的元数据,比如文件大小,文件的修改时间;
fs.readFile/fs.readFileSync:异步/同步读取文件
fs.writeFile/fs.writeFileSync:异步/同步写入文件
fs.readdir/fs.readdirSync:读取文件夹内容
fs.unlink/fs.unllinkSync:删除文件
fs.rmdir/fs.rmdirSync:只能删除空文件
fs.watchFile:监视文件的变化
let fs = require("fs");
fs.stat("a.txt",(err,stat)=>{
if (err){
console.log(err)
} else {
// console.log(stat)
console.log('size:'+stat.size)//size:37
console.log('mtime:'+stat.mtime)//mtime:Tue Oct 02 2018 14:01:04 GMT+0800 (GMT+08:00)
console.log('isFile:'+stat.isFile())//isFile:true
console.log('isDirectory:'+stat.isDirectory())//isDirectory:false
}
});
let fs = require("fs");
//读取文件内容
/*fs.readFile("a.txt",(err,data)=>{
if (err){
throw err
}
console.log(data)//得到buff
console.log(data.toString())//大河向东流,齐德龙东强嘚呛
});*/
//向文件中写入内容
/*let data = "冒蓝光的加特林,哒哒哒"
fs.writeFile("c.txt",data,(err)=>{
if (err) throw err
console.log('执行写入文件')
});*/
/*获取文件中文件的名字*/
/*let fs = require("fs");
let path = require('path');
let target = './demo'
fs.readdir(target,(err,files)=>{
console.log(files)//[ '08_fs-demo01.js', 'a.txt', 'b.txt', 'c.txt', 'd1' ]
//遍历目录里面文件是否是文件夹
files.forEach(f=>{
// console.log(f)
fs.stat(path.join(target,f),(err,stat)=>{
if (err) throw err
console.log(f+":"+stat.isDirectory())
})
})
});*/
/*删除文件*/
fs.unlink("demo/a.txt",(err)=>{
if (err){
console.log("删除失败")
}
});
//删除文件夹 rmdir:只能删除空文件夹
//使用第三方模块 fx-extra
let fsExtra = require("fs-extra");
fsExtra.remove("demo");//删除文件夹
//监视文件变化
fs.watchFile("a.txt",(curre,pre)=>{
console.log('curre mtime: '+curre);
console.log('pre mtime' + pre) ;
});
6.stream操作大文件:pipe()的使用
Node提供了流对象读取大文件;其实就是把所有的数据分成一个个的小数据块(chunk),一次读取一个chunk,多次读取特别大的文件;(写入也是同理).
//大文件的复制
let reader = fs.createReadStream(`a.txt`);//假设a.txt是1G以上的大文件
let writer = fs.createWriteStream("a-copy.txt");
reader.pipe(writer)
7.Promise和async/await
7.1只使用回调函数完成需求:
/*需求:
* 先判断一个文件是文件还是文件夹,如果是文件夹就读取这个文件夹下的文件列表,
* 并找出结尾是.txt的文件,然后获取它的文件大小;
* */
let fs = require("fs");
let path = require("path");
function noPromise() {
let target = "test";
//读取文件
fs.stat(target,(err,stat)=>{
if (err) throw err
//如果是文件夹,如果是文件夹,就读取下面的文件列表
if (stat.isDirectory()){
//读取文件夹,读出来的文件夹是files
fs.readdir(target,(err,files)=>{
//遍历files
files.forEach(f=>{
//判断是否是.txt文件
if (path.extname(f) === '.txt'){
//如果是,就打印出来
fs.stat(path.join(target,f),(err,stat)=>{
console.log(f+":"+stat.size)
})
}
})
})
}
});
}
7.2使用promise对象进行包装
//使用promise对象将含有回调方法的代码进行包装
let promise = new Promise((resolve, reject)=>{
//当异步操作成功时,执行的是resolve()方法
//当异步操作失败时,执行的是reject()方法
fs.readFile('c.txt',(err,data)=>{
if (err){
reject(err);
}else {
resolve(data);
}
})
});
//直接使用promise,问题是仍然需要回调,不建议使用;
promise.then((data)=>{
console.log("异步操作成功:"+data.toString())
}).catch((err)=>{
console.log("操作失败:"+err)
});
7.3使用aysnc/await调用promise对象
//使用promise对象将含有回调方法的代码进行包装
let promise = new Promise((resolve, reject)=>{
//当异步操作成功时,执行的是resolve()方法
//当异步操作失败时,执行的是reject()方法
fs.readFile('c.txt',(err,data)=>{
if (err){
reject(err);
}else {
resolve(data);
}
})
});
//使用async/await语法来调用promise对象
async function asyncDemo() {
try {
let data = await promise
console.log(data.toString())
}catch (e) {
console.log(e)
}
}
asyncDemo();
7.4 使用第三方封装promise!!!
对7.1中的需求代码进行封装
//使用promise和aysnc/await对上面代码进行优化
let util = require('util');
async function promise() {
let target = "test";
//使用util将fs.stat转为一个可以获得promise对象的方法
let pstat = util.promisify(fs.stat);
let stat = await pstat(target);
if (stat.isDirectory()) {
//将fs.readdir转为一个可以获得promise对象的方法
let preaddir = util.promisify(fs.readdir);
let files = await preaddir(target)
files.forEach(async (f) =>{
if (path.extname(f)==='.txt'){
let stat01 = await pstat(path.join(target,f))
console.log(stat01.size)
}
})
}
}
promise();
网友评论