十五、Node.js-fs模块(中)

有了上一篇JS同步异步知识的铺垫,我们一起学习一下fs模块的同步和异步知识:

Node.js内置的fs模块就是文件系统模块,负责读写文件。

和所有其它JavaScript模块不同的是,fs模块同时提供了异步和同步的方法。

异步读文件

按照JavaScript的标准,异步读取一个文本文件的代码如下:

'use strict';

var fs = require('fs');

fs.readFile('sample.txt', 'utf-8', function (err, data) {
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

请注意,sample.txt文件必须在当前目录下,且文件编码为utf-8

异步读取时,传入的回调函数接收两个参数,当正常读取时,err参数为nulldata参数为读取到的String。当读取发生错误时,err参数代表一个错误对象,dataundefined。这也是Node.js标准的回调函数:第一个参数代表错误信息,第二个参数代表结果。后面我们还会经常编写这种回调函数。

由于err是否为null就是判断是否出错的标志,所以通常的判断逻辑总是:

if (err) {
    // 出错了
} else {
    // 正常
}

同步读文件

除了标准的异步读取模式外,fs也提供相应的同步读取函数。同步读取的函数和异步函数相比,多了一个Sync后缀,并且不接收回调函数,函数直接返回结果。

fs模块同步读取一个文本文件的代码如下:

'use strict';

var fs = require('fs');

var data = fs.readFileSync('sample.txt', 'utf-8');
console.log(data);

可见,原异步调用的回调函数的data被函数直接返回,函数名需要改为readFileSync,其它参数不变。

如果同步读取文件发生错误,则需要用try...catch捕获该错误:

try {
    var data = fs.readFileSync('sample.txt', 'utf-8');
    console.log(data);
} catch (err) {
    // 出错了
}

异步还是同步

fs模块中,提供同步方法是为了方便使用。那我们到底是应该用异步方法还是同步方法呢?

由于Node环境执行的JavaScript代码是服务器端代码,所以,绝大部分需要在服务器运行期反复执行业务逻辑的代码,必须使用异步代码,否则,同步代码在执行时期,服务器将停止响应,因为JavaScript只有一个执行线程。

服务器启动时如果需要读取配置文件,或者结束时需要写入到状态文件时,可以使用同步代码,因为这些代码只在启动和结束时执行一次,不影响服务器正常运行时的异步执行。

例题:打印出某个文件夹下面所有的文件夹:

错误代码:

fs.readdir("html",function (err,data) {//读取出html目录下的所有文件和文件夹
    if (err){
        console.log(err);
    }else{
        console.log(data);
        for(var i=0;i<data.length;i++){//data.length=3,最后的i值也等于3,由于fs是异步的
            fs.stat(data[i],function (erroy,stats) {//所以这里其实相当于fs.stat(data[3],function (erroy,stats),出现了索引越界
                if (erroy){
                    console.log(erroy);
                }else{
                    if (stat.isDirectory()){
                        console.log(data[i]);
                    }
                }
            })
        }
    }
})

正确代码:

fs.readdir("html", function (err, files) {
    if (err) {
        console.log(err);
    } else {
        (function getDir(i) {
            if (i == files.length) {//結束調用
                return false;
            }
            fs.stat('html/'+files[i], function (erroy, stats) {
                if (erroy){
                    console.log(erroy);
                }else{
                    if (stats.isDirectory()) {
                        console.log(files[i]);
                        getDir(i + 1)//递归完成调用
                    }
                }
            })
        })(0)
    }
})

 

posted @ 2019-04-24 14:07  指尖下的世界  阅读(283)  评论(0编辑  收藏  举报
/* 看板娘 */ /*炸泡*/
/* 鼠标点击求赞文字特效 */