首页 > 代码库 > 基于Node.js的文件服务器(使用Q重构代码)

基于Node.js的文件服务器(使用Q重构代码)

        之前写过一篇文章,简单介绍了一个基于Node.js的静态文件服务器。那时还只是个人兴趣。最近又有了关于服务器的新的需求,我就想花点时间,好好研究一下。所以把之前的代码拿出来重构了一番,整体代码变得干净很多。

        首先最新Node.js是支持generator的,所谓generator,就是javascript中的协程(半协程),不过功能稍弱,仅仅是为了解决js中凶名赫赫的callback hell而诞生的。这里我并没有使用generator,而是使用promise(饭要一口一口吃,先弄明白promise再去学习generator)。promise并不是新的语法,而是一种书写方式。最出名的实现是Q。

        关于Q的学习资料可以看这里,非常清楚。

server.js的代码:

'use strict';

var CONFIG = {
	'host': '127.0.0.1',
	'port': 9527,
	'site_base': './site',
	'file_expiry_time': 0, // HTTP cache expiry time, minutes
	'directory_listing': true
};
	
var MIME_TYPES = {
	'.txt': 'text/plain',
	'.md': 'text/plain',
	'': 'text/plain',
	'.html': 'text/html',
	'.css': 'text/css',
	'.js': 'application/javascript',
	'.json': 'application/json',
	'.jpg': 'image/jpeg',
	'.png': 'image/png',
	'.gif': 'image/gif',
	'.zip': 'text/plain',
	'.cfg': 'text/plain'
};
	
var EXPIRY_TIME = (CONFIG.file_expiry_time * 60).toString();
	
var http = require('http');
var Path = require('path');
var Crypto = require('crypto');
var Custard = require('./custard/custard');
var Q = require('q');
var fs = require('./filesystem')
// An object representing a server response

function ResponseObject( metadata ){
	this.status = metadata.status || 200;
	this.data = http://www.mamicode.com/metadata.data || false;>

filesystem.js的代码(在server.js中有用到,只是使用Q简单的封装了下node.js的异步文件操作):

var Q = require('q')
var fs = require('fs')

// 使用Q封装回调形式的文件操作函数
var fs_readFile = Q.nfbind(fs.readFile);
var fs_readdir = Q.nfbind(fs.readdir);
var fs_stat = Q.nfbind(fs.stat);

function exists(path) {
    var defer = Q.defer();

    fs.exists(path, function(exists) {
        if (exists) {
            defer.resolve(exists);
        } else {
            defer.reject(exists);
        }
    });
    return defer.promise;
}

function readFile(path) {
    return fs_readFile(path);
}

function readdir(path) {
    return fs_readdir(path);
}

function stat(path) {
    return fs_stat(path)
}



// 同步函数,直接调用
function statSync(path) {
    return fs.statSync(path);
}

function readFileSync(path) {
    return fs.readFileSync(path)
}

module.exports.exists = exists;
module.exports.readFile = readFile;
module.exports.readFileSync = readFileSync;
module.exports.readdir = readdir;
module.exports.stat = stat;
module.exports.statSync = statSync;


        说实话,即便是重构后的代码,也不是非常简洁。使用Q最主要是解决多层回调的问题的。在上面的代码中,其实没有太多的多层调用,所以体现的不是非常明显,不过项目大了,会有显著的效果。

        即便使用Q之后,调试起来还是比较麻烦,因为我们无法清晰的知道这个函数是谁,在什么时候调用的,也就是说,很多时候我们获取不到调用堆栈(可以获取到,但是获取到的信息几乎无意义,因为函数都是在Q的task中调用的)。

        关于Q封装Node.js的异步函数,这里需要注意一下filesystem.js中的exists()函数。Q.nfbind做的事情其实就是exists中所做的。函数第一个参数必须是error,第二个参数必须是data,这样的函数才能够直接使用Q.nfbind封装,像fs.exits函数,只有一个参数,所以无法使用Q.nfbind封装。

基于Node.js的文件服务器(使用Q重构代码)