2013-06-12 97 views
6

朋友已经问了一个有趣的问题,我试了几件事情,但没有用,有什么办法来重写节点JS模块?节点JS覆盖标准模块

例如,我想重写readFile函数来使用S3存储区而不是文件系统。 IE:

var fs = require('fs'); 

fs.readFile('my_text_file.txt', ...); 

实际运行这样的事情

FileSystem.readFile = function() { 
    // Connect to S3 and retrieve remote file 
} 

我已经试过了原型,但似乎他们已经建立了本地模块没有__proto__对象,他们没有一个.constructor属性这对任何人都意味着什么。

我想过使用Nodes VM,但这太严格了,因为我希望用户能够通过npm安装模块并使用它们。

我其实是来创造一个新的模块最近的(因为我不能把一个名为fs.js文件在我的文件夹node_modules,并要求它,它只是被忽略),只是硬设定的fs的值我想要什么,但这不是很对,我希望用户使用require('fs')并使用我的自定义功能。

这是否可能,而不编译我自己的版本的节点JS?

+0

我还没有使用node.js,所以这可能根本无法工作。你可以尝试看看是什么函数声明'FileSystem',然后用它作为你的自定义对象(“子类”它)的原型。 MyFS = {FileSystem.call(this);}; MyFs.prototype = new FileSystem();或者使用诸如goog.base和goog.inherit之类​​的东西来创建一个子类,该子类可以将其称为“父”函数并处理传递给构造函数的参数:http://docs.closure-library.googlecode.com/git/closure_goog_base。 js.html请注意,badse使用'arguments.callee.caller',它在ecma 5中不起作用,因此您必须重新编写它。 – HMR

+0

关于goog.base和goog.inherits的好文章在这里:http://bolinfest.com/essays/googbase.html – HMR

+0

为了说明的目的,我制作了'FileSystem',模块没有'__proto__'对象,因此没有构造函数。我得到的最接近的是直接设置对象的属性,并包括另一个脚本,但我想'require('fs')',它有我的自定义功能 –

回答

11

我觉得有责任强烈警告你不要覆盖原生函数。话虽这么说,这将工作:

main.js:

var fs = require('fs'), 
    oldReadFile = fs.readFile; 

fs.readFile = function (filename, options, callback) { 
    console.log('hey!'); 
    oldReadFile(filename, options, callback) 
}; 

var other = require('./other'); 
other.test(); 

other.js:

var fs = require('fs'); 

exports.test = function() { 
    fs.readFile('./main.js', {encoding: 'utf8'}, function (err, data) { 
    console.log(err, data); 
    }); 
}; 

你需要用自己的包裹你的用户脚本首先覆盖你想要什么。

+0

+1用于警告。不要混淆基本模块。 – aggsol

+0

我知道,我不会亲自。至少没有'vm',但这是一个有趣的问题。然而,这与我已经尝试过的相同,并不是他想要的。 –

+0

@Laurent避免覆盖原生函数的特定原因?我打算做一些类似的操作来覆盖数据库的读写操作。 – DanMatlin