Node.js 读取文件
读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
以下是同步和异步读取文件的方式:
var fs = require("fs");
module.exports = {
readfileSync : function(path){//同步读取
var data = fs.readFileSync(path,'utf-8');
console.log(data);
console.log("同步方法执行完毕");
},
readfile : function(path){//异步执行
fs.readFile(path,function(err,data){
if(err){
console.log(err);
}else{
console.log(data.toString());
}
});
console.log("异步方法执行完毕");
}
}
下面进行同步读取文件的操作:
var http = require('http');
var optfile = require('./fs_read');//相当于把fs_read.js嵌入当前文件
http.createServer(function(request,response){
response.writeHead(200,{'Content-Type' : 'text/html; charset=UTF-8'});
if(request.url != '/favicon.ico'){
optfile.readfileSync('./login.html');//路径相对于主程序的路径
response.end('ok');
console.log("主程序结束");
}
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000');
结果如下:
以下是异步读取文件的方式:
var http = require('http');
var optfile = require('./fs_read');//相当于把fs_read.js嵌入当前文件
http.createServer(function(request,response){
response.writeHead(200,{'Content-Type' : 'text/html; charset=UTF-8'});
if(request.url != '/favicon.ico'){
optfile.readfile('./login.html');//路径相对于主程序的路径
response.end('ok');
console.log("主程序结束");
}
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000');
如果我们想把文件内容输出在浏览器呢?我们该怎么做?按照以往同步编程的思路,我们这么做:
var fs = require("fs");
module.exports = {
readfileSync : function(path){//同步读取
var data = fs.readFileSync(path,'utf-8');
console.log(data);
console.log("同步方法执行完毕");
},
readfile : function(path,res){//异步执行
fs.readFile(path,function(err,data){
if(err){
console.log(err);
}else{
res.write(data.toString())
console.log(data.toString());
}
});
console.log("异步方法执行完毕");
}
}
在读取文件的方法加一个参数,把response传进来,然后打印。主程序中把response传入:
var http = require('http');
var optfile = require('./fs_read');//相当于把fs_read.js嵌入当前文件
http.createServer(function(request,response){
response.writeHead(200,{'Content-Type' : 'text/html; charset=UTF-8'});
if(request.url != '/favicon.ico'){
optfile.readfile('./login.html',response);//路径相对于主程序的路径
response.end('ok');
console.log("主程序结束");
}
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000');
我们看看有什么结果:
我们发现报错了。原因是因为,这个是异步读取。主程序response已经执行到了end(),但是执行完之后,读取文件的方法才读取完成,这个时候readerfile方法里面的response已经执行了end()方法了,如果没法再执行write()方法了。
如果在异步编程的时候,往往就不像同步那么简单了,我们该如果做呢?
下面我们使用闭包的方法来改造之前的代码:
var http = require('http');
var optfile = require('./fs_read');
http.createServer(function(request,response){
response.writeHead(200,{'Content-Type' : 'text/html; charset=UTF-8'});
if(request.url != '/favicon.ico'){
function recall(data){ //等待readfile执行完之后回调
response.write(data);
response.end('ok');
}
optfile.readfile('./login.html',recall);//传入闭包函数
console.log("主程序结束");
}
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000');
var fs = require("fs");
module.exports = {
readfileSync : function(path){//同步读取
var data = fs.readFileSync(path,'utf-8');
console.log(data);
console.log("同步方法执行完毕");
},
readfile : function(path,recall){//异步执行
fs.readFile(path,function(err,data){
if(err){
console.log(err);
}else{
recall(data); //回调recall函数,它是闭包函数,它会存储原来的response对象
console.log(data.toString());
}
});
console.log("异步方法执行完毕");
}
}
最后我们就能在浏览器上看到结果了。
接下来我们再根据之前我上一篇博文的Node.js的路由http://blog.csdn.net/cckevincyh/article/details/78305846来改造我们的代码。
在router.js中我们进行如下改造:
var optfile = require('./fs_read');
module.exports = {
login : function(req,res){
function recall(data){ //等待回调
res.write(data);
res.end(''); //不写则没有http协议尾
}
optfile.readfile('login.html',recall);
},
register : function(req,res){
function recall(data){ //等待回调
res.write(data);
res.end(''); //不写则没有http协议尾
}
optfile.readfile('register.html',recall);
}
}
将闭包的回调函数recall()和读取文件的方法都放进来。
在主程序中,我们不需要加上response.end(),因为我们要等待回调函数recall执行完毕后才能结束,所以response.end()放在recall()中。
var http = require('http');
var url = require('url');
var router = require('./router');
http.createServer(function(request,response){
response.writeHead(200,{'Content-Type' : 'text/html; charset=UTF-8'});
if(request.url != '/favicon.ico'){
var pathname = url.parse(request.url).pathname;
pathname = pathname.replace(/\//,''); //替换掉前面的'/'
console.log("Request for " + pathname + " received.");
router[pathname](request,response);
}
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000');
接下来我们启动,在浏览器就能看到结果了: