场景需求一:判断服务器上面有没有upload目录,如果没有,则创建这个目录,如果有的话不做操作
实现方法一:
步骤一:封装一个根据传入目录路径的参数创建目录的函数
const fs=require('fs');
function mkdir(dir){
fs.mkdir(dir,(err)=>{
if(err){
console.log(err);
return;
}
})
}
步骤二:定义一个目标目录路径的变量(path),先用fs.stat判断有没有upload目录,如果有upload但是upload不是目录的话,先去执行删除upload文件再去执行创建upload目录
var path='./upload'
fs.stat('./upload',(err,data)=>{
if(err){
//执行创建目录
mkdir(path)
return;
}
if(!data.isDirectory()){
console.log('upload不是目录')
//首先先去删除文件再去执行创建目录
fs.unlink(path,(err)=>{
if(!err){
mkdir(path);
}else{
console.log('请检查传入的数据是否正确')
}
})
}
})
实现方法二:
步骤一:cnpm i mkdirp --save
步骤二:var mkdirp =require('mkdirp');
步骤三:
mkdirp('./upload').then(made =>
console.log(`made directories, starting with ${made}`))
场景需求二:wwwroot文件下下面有img css js 以及index.html,找出wwwroot 目录下面的所有目录,然后放在一个数组里面
该构建目录结构为:黄色框为入口文件代码
失败的方法一之错误的写法:没有考虑到异步给代码带来的影响
场景带入:
for(var i=0;i<3;i++){
setTimeout(function(){
console.log('i', i)
},100)
} // i 3 i 3 i 3
function getData(){
//ajax
setTimeout(function(){
var name='张三'
},1000)
return name;
}
// //外部获取异步方法里面的数据
console.log(getData()) //name is not defined
//通过回调函数获取异步方法里面的数据
function getData(callback){
//ajax
setTimeout(function(){
var name='张三';
callback(name)
},1000)
}
//外部获取异步方法里面的数据
getData(function(name){
console.log(name)
})
失败的方法一的基本思路:声明一个空数组(dirArr)和一个目标路径('./wwwroot'),利用fs.readdir对目标路径目录进行读取,如果该目录下有目录可读取数据会保存在data里,接着对data数据进行循环遍历筛选,想要利用fs.stat对data中判断为目录的数据放进数组dirArr中。
失败的方法一:
var dirArr=[];
var path='./wwwroot'
fs.readdir(path,(err,data)=>{
if(err){
console.log(err);
return;
}
console.log('data',data) //第二被执行--数据确实有
for(var i=0;i<data.length;i++){
fs.stat(path+'/'+data[i],(error,stats)=>{
if(stats.isDirectory()){
dirArr.push(data[i])
}
})
}
console.log('dirArr111', dirArr)
})
console.log('dirArr222', dirArr) //第一被执行--因为fs.readdir异步
失败的方法一总结:
for循环中的 fs.stat 是异步方法,
在for循环执行中时 data 中的数据无法和预期结果一致
改造的成功的方法二的基本思路利用IIFE和递归实现
var dirArr=[];
var path='./wwwroot'
fs.readdir(path,(err,data)=>{
if(err){
console.log(err);
return;
}
(function getDir(i){
if(i==data.length){
console.log('dirArr', dirArr)
return;
}
fs.stat(path+'/'+data[i],(error,stats)=>{
if(stats.isDirectory()){
dirArr.push(data[i])
}
getDir(i+1)
})
})(0)
})
改造的进阶的方法三的基本思路:通过async 和 await。先定义一个isDir的方法判断一个资源到底是目录还是文件,该方法如果是目录返回true,不是则返回false,再去获取wwwroot里面的所有资源循环遍历判断
async function isDir(path){
return new Promise((resolve,reject)=>{
fs.stat(path,(error,stats)=>{
if(error){
console.log(error)
reject(error)
}
if(stats.isDirectory()){
resolve(true)
}else{
resolve(false)
}
})
})
}
function main(){
var path='./wwwroot'
var dirArr=[];
fs.readdir(path, async (err,data)=>{
//---await得用在async的方法里面
if(err){
console.log(err);
return;
}
for(var i=0;i<data.length;i++){
if(await isDir(path+'/'+data[i])){
dirArr.push(data[i])
}
}
console.log(dirArr)
})
}
main();
async和await的使用思路:
/**
* async是'异步'的简写,
而await可以认为是async的简写。
* 所以很好理解async用于申明一个异步的function,
而await用于等待一个异步方法执行完成
*
* 简单理解
* async是把方法变成异步
* await是等待异步方法执行完成
*/
//普通方法
function test(){
return '你好node.js'
}
console.log(test()) //你好node.js
async function test(){
return '你好node.js'
}
console.log(test()) //Promise { '你好node.js' }
错误的写法:
错误的写法:
错误的写法:
错误的写法:
async function test(){
return '你好node.js'
}
console.log( await test()) //错误
---await得用在async的方法里面
---await得用在async的方法里面
---await得用在async的方法里面
正确的写法:
正确的写法:
正确的写法:
正确的写法:
async function test(){
return '你好node.js'
}
async function main(){
var data=await test(); //获取异步方法里面的数据
console.log(data)
}
main(); /你好node.js
通过async封装一个异步方法并返回一个promise
async function test() {
return new Promise((res,rej)=>{
setTimeout(()=>{
var name='异步数据';
res(name)
},100)
})
}
//await得用在async的方法里面
async function main(){
var data=await test();
console.log(data) //异步数据
}
main();
- 该构建目录的结构为:
readFileSync读取文件
//当文件过大时会发生内存爆仓
const fs = require("fs");
// let res = fs.readFileSync("1.txt");
// console.log(res.toString());
fs.createReadStream从文件流中读取数据
var fs=require('fs')
var readStream=fs.createReadStream('./input.txt')
var count=0;
var str='';
//监听读取数据的事件
//监听流的数据
readStream.on('data',(data)=>{
str+=data;
count++;
})
readStream.on('end',()=>{
console.log(str,count)
})
readStream.on('error',(err)=>{
console.log(err)
})
fs.createWriteStream从文件流中写入数据
var fs=require('fs');
var data= '我是从数据库获取的数据,我要保存起来';
var str='';
for(var i=0;i<500;i++){
str+='我是从数据库获取的数据,我要保存起来/n'
}
var writeStream=fs.createWriteStream('./ouput.txt')
writeStream.write(str);
//标记写入完成--才能触发finish
writeStream.end();
writeStream.on('finish',()=>{
console.log('写入完成')
})
一边创建可读流一边创建可写流进行普通读写操作
//创建一个可读流
var readStream=fs.createReadStream('./input.txt')
//创建一个可写流
var writeStream=fs.createWriteStream('./ouput.txt')
//普通读写操作
//读取input.txt文件内容并将内容复制写入到ouput.txt文件中
readStream.pipe(writeStream)
console.log('执行成功')
- 案例一:边创建一个65kb的文件的可读流,边创建可写流的文件并导入进去65kb的文件
const fs = require("fs");
//创建可读流
let rs = fs.createReadStream("65kb");
//buffer打印了两次说明数据被拆分了两次
//创建可写流
let ws = fs.createWriteStream("2.txt");
//边读边写
rs.pipe(ws);
let num = 0;
let str = "";
rs.on("data",chunk=>{
num++;
str += chunk;
// console.log(chunk);
console.log(num); //2 读取两次
})
// 流读取完成了的事件;
rs.on("end",()=>{
console.log(str); //再这里读取完整的数据
})
// 流会把数据分成64kb的小文件(64kb一组)传输;
// 创建一个65kb的文件
let buffer = Buffer.alloc(65*1024);
fs.writeFile("64kb",buffer,err=>{
if(err){
return console.log(err);
}
console.log("写入成功");
})