所以我在纯node.js中编写我的Web服务器,只对bluebird
使用promisify
。这一直困扰我一个星期,我无法决定我应该使用哪一个。我已经阅读了关于这两个主题的大量帖子,博客和文档,请根据您自己的工作经验回答,谢谢。这里有详细的总结和相关问题。
这两种方法都经过测试,它们都很有效。但我无法测试性能,我只有自己的基本网站文件(html,css,img,小型数据库等),而且我从来没有管理过视频文件和庞大的数据库。
下面是代码部分,为您提供基本的想法(如果您真的知道使用哪一个,不用费心阅读代码,为您节省一些时间),这个问题与逻辑无关,所以您只需阅读虚线之间的部分。
关于fs.createReadStream
:
优点:适用于大型文件,它一次读取一块,节省内存,管道非常智能
缺点:同步,不能被宣传(流是一个不同的概念承诺,太难做,不值得)。
//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
:
优点:异步,可以轻松实现,这使得代码真正易于编写(开发)和读取(维护)。还有其他好处我尚未掌握,如数据验证,安全性等
缺点:对于大文件不好。
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);
});
//----------------------------------------------------
}
};
以下是我的选择:
•简单方法:将fs.createReadStream
用于所有事情
•正确的方法:仅将fs.createReadStream
用于大文件
•实用方法:在发生相关问题之前使用fs.readFile
,然后使用fs.createReadStream
处理这些问题。
我的最终决定是仅对大文件使用fs.createReadStream(我将为大文件创建一个函数),并为其他所有文件创建fs.readFile。这是一个好的/正确的决定吗?还有更好的建议吗?
P.S.(不重要):
我真的很喜欢自己构建基础架构,为了给你一个想法,当我实例化服务器时,我可以像这样设置路由,并自定义任何我想要的东西。请不要建议我使用框架:
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"
}
]
}
答案 0 :(得分:1)
让我们讨论实际的实际方法。
createReadStream
和readFile
都非常有用 - createReadStream
在大多数情况下效率更高,如果您处理大量文件(而非提供服务),请考虑它。< / p>
您应该从静态文件服务器提供静态文件 - 大多数PaaS Web主机会自动为您执行此操作,如果您set up an environment yourself,您将发现自己反向代理节点,无论如何都应该服务于IIS之类的服务器静态文件。
这仅适用于静态文件,同样,如果您阅读它们并将它们多次转换,则您的问题变得非常相关。
fs.readFileAsync
我大量使用readFile
来读取缓冲区并使用它们,而createReadStream
可以提高延迟 - 总体而言,您应该获得类似的吞吐量,API更容易使用,更高级别
createReadStream
。readFile
。