Node.js Web服务器fs.createReadStream vs fs.readFile?

所以我正在写我的web服务器在纯node.js,只使用bluebird promisify 。 这一直困扰我一个星期,我不能决定我应该使用哪一个。 我已经阅读了大量关于这两个主题的post,博客和文档,请根据您自己的工作经验回答,谢谢。 这里有详细的总结和相关的问题。

两种方法都经过testing,它们都很好。 但是我不能testing性能,我只有自己的基本网站文件(html,css,img,小型数据库等),而且我从来没有pipe理过的video文件和庞大的数据库。

下面是代码部分,给你一些基本的想法(如果你真的知道使用哪一个,不用费心去阅读代码,为了节省一些时间),这个问题不是关于逻辑,所以你可以阅读虚线。

关于fs.createReadStream
优点:对于大文件很好,它一次读取一个块,节省内存和pipe道真的很聪明。
缺点:同步,不能被promisified(stream是一个不同的概念承诺,太难做,不值得)。

 //please ignore IP, its just a custom name for prototyping. IP.read = function (fpath) { //---------------------------------------------------- let file = fs.createReadStream(fpath); file.on('error', function () { return console.log('error on reading: ' + fpath); }); return file; //---------------------------------------------------- }; //to set the response of onRequest(request, response) in http.createServer(onRequest). IP.setResponse = function (fpath) { let ext = path.extname(fpath), data = IP.read(fpath); return function (resp) { //---------------------------------------------------- //please ignore IP.setHeaders. resp.writeHead(200, IP.setHeaders(ext)); data.pipe(resp).on('error', function (e) { cosnole.log('error on piping ' + fpath); }); //---------------------------------------------------- } }; 

关于fs.readFile
优点:asynchronous,可以很容易地promisified,这使得代码真正的写(开发)和阅读(维护)很容易。 还有其他的好处,我还没有得到,如数据validation,安全等。
缺点:对于大文件不好。

 IP.read = function (fpath) { //---------------------------------------------------- let file = fs.readFileAsync(fpath); return file; //---------------------------------------------------- }; //to set the response of onRequest(request, response) in http.createServer(onRequest). IP.setResponse = function (fpath) { const ext = path.extname(fpath); return function (resp) { //---------------------------------------------------- IP.read(fpath).then((data) => { resp.writeHead(200, IP.setHeaders(ext)); resp.end(data); }).catch((e) => { console.log('Problem when reading: ' + fpath); console.log(e); }); //---------------------------------------------------- } }; 

这是我的select:
简单的方法:使用fs.createReadStream来处理所有事情。
•正确的方法: fs.createReadStream大文件使用fs.createReadStream
实际的方法:使用fs.readFile处理所有事情,直到出现相关问题,然后使用fs.createReadStream处理这些问题。

我最后的决定是只使用fs.createReadStream来处理大文件(我将为大文件创build一个函数),而对于其他所有文件则使用fs.readFile。 这是一个好的/适当的决定? 有更好的build议吗?

PS(不重要):
我真的很喜欢自己构build基础架构,给你一个想法,当我实例化一个服务器,我可以像这样设置路由,并自定义任何或我想要的。 请不要build议我使用框架:

 let routes = [ { method: ['GET', 'POST'], uri: ['/', '/home', '/index.html'], handleReq: function () {return app.setResp(homeP);} }, { method: 'GET', uri: '/main.css', handleReq: function () {return app.setResp(maincssP);} }, { method: 'GET', uri: '/test-icon.svg', handleReq: function () {return app.setResp(svgP);} }, { method: 'GET', uri: '/favicon.ico', handleReq: function () {return app.setResp(iconP);} } ]; 

或者我可以自定义它,并把它放在一个像这样的config.json文件中:

 { "routes":[ { "method": ["GET", "POST"], "uri": ["/", "/home"], //I will create a function(handleReq) in my application to handle fpath "fpath": "./views/index.html" }, { "method": "GET", "uri": "/main.css", "fpath": "./views/main.css" }, { "method": "GET", "uri": "/test-icon.svg", "fpath": "./views/test-icon.svg" } ] } 

我们来讨论一下实际的实际方法。

您不应该在生产中从Node提供静态文件

createReadStreamreadFile都非常有用 – 在大多数情况下, createReadStream更加有效,如果你正在处理大量的文件(而不是服务于它们),那就考虑它。

你应该从静态文件服务器提供静态文件 – 大多数PaaS的networking主机自动为你做这个,如果你自己设置一个环境,你会发现自己反向代理节点,像IIS应该服务于静态文件。

这只对静态文件是真实的,再一次,如果你阅读并转换它们多次你的问题变得非常相关。

为了其他目的,您可以安全地使用fs.readFileAsync

我使用readFile读取文件到缓冲区并使用它们很多,而createReadStream可以提高延迟 – 总体而言,您应该获得相似的吞吐量,并且API更易于使用和更高级别。

所以最后

  • 如果您正在提供静态文件,则不要从生产中的Node执行。
  • 如果您要将文件转换为stream并且延迟非常重要,请使用createReadStream
  • 否则,更喜欢readFile