为了自我保护,我正在尝试编写一个纯node.js Web服务器。这样做的目的是完全避免使用预先编写的中间件或任何非默认的node.js模块来加载静态HTML,CSS和JavaScript,并强迫自己学习纯正的node.js方法的来龙去脉。 。
我已经启动并运行它,并对其进行了几次测试,在我决定通过几次在静态页面上快速点击刷新来对它进行压力测试之前,它似乎工作得很好。
前3-4次装弹效果很好。之后,静态HTML文件调用的CSS或JavaScript文件均不会加载。
这是我的文件读取代码:
fs.readFile(filename, function(err, contents) {
if(err) {
throw err;
} else {
res.setHeader("Content-Length", contents.length);
res.setHeader("Content-Type", validExtensions[ext]);
res.statusCode = 200;
res.write(contents);
res.end();
}
});
(validExtensions
只是成对的扩展名及其相应的mime类型的数组。)
当存在HTML文件,CSS文件和JavaScript文件时,在页面加载期间将调用此函数3次。同样,它可以正常工作,直到突然不起作用为止。然后,如果我再刷新一次,一切就恢复了。
我怀疑这是怎么回事,有时它会在CSS或JavaScript文件完成之前完成HTML文件。
我能想到的唯一解决方法是非常讨厌的。我可以创建一个单独的函数来处理不是HTML的所有文件,并使该过程保留剩余文件的数量。然后,我可以while
在处理HTML的函数中使用一个循环,并阻止该循环执行res.end()
直到该计数为零为止,但这听起来既丑陋又可能消耗资源。
或者,我可以使用同步加载所有非HTML文件的(甚至更糟的)解决方法,但是由于该调用将来自本来是异步处理的函数中,所以我真的不想这样做。
如果我只是尝试构建一个静态站点,则可以使用http-server或express或许多出色的解决方案之一来提供静态文件,但是它们都具有广泛的模块依赖性,我正在尝试获得该解决方案。没有他们就完成了。
有没有一种优雅而纯粹的方法来确保res.end()
在所有非HTML文件完成其工作之前不会加载HTML?
编辑:所以任何人都可以看到整个上下文,整个项目,它的内容,位于github上的https://github.com/GoodDamon/customserver
您的问题在于customServer.url
。如果要打开浏览器的开发工具并检查的内容app.css
,您会发现它有时仅填充以下行:
console.log("CustomServer successfully loaded!");
...恰好与app.js
文件的内容相同。巧合?没有。如果您查看节点控制台的输出,您会不时看到以下内容:
10/11/2015 5:42:09 PM: New client request: /css/app.css - Method: GET
10/11/2015 5:42:09 PM: Client requested a file. Testing extension validity...
10/11/2015 5:42:09 PM: File extension .css is VALID. Testing availability...
10/11/2015 5:42:09 PM: New client request: /js/app.js - Method: GET
10/11/2015 5:42:09 PM: Client requested a file. Testing extension validity...
10/11/2015 5:42:09 PM: File extension .js is VALID. Testing availability...
10/11/2015 5:42:09 PM: File is AVAILABLE. Providing to client.
10/11/2015 5:42:09 PM: File is AVAILABLE. Providing to client.
如您所见,浏览器首先请求app.css
,紧接着是app.js
。因为“向客户端提供”两行都在底部,所以您知道节点服务器尚未完成对第一个请求的处理。客户端最终接收到的是app.js
两次,分别以.css和.js文件发送。
为什么是这样?从理论上讲,每个命中节点服务器的客户端请求都应隔离到其自己的事件循环中。不应有交叉污染。问题在于customServer.url
,这是您将传入req.url
值分配给的内容。因为它不在两个客户端请求的范围之内,所以每个请求都会覆盖前一个的值。
对于同步编程而言,这不是问题,但是node.js完全是异步的,并且将尽快执行所有请求,无论是否还有待处理的请求。您的fs.stat()
呼叫需要花费一些时间才能执行,并且很有可能在成功/错误回调执行之前,另一个请求已到达服务器。
tl; dr:此行-customServer.getFile(customServer.url, res, ext);
将同一文件发送到2个不同的请求,因为您正在customServer.url
用每个新请求覆盖。在请求范围内跟踪您的请求URL!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句