自定义node.js Web服务器不会完成加载CSS和JavaScript

为了改善自我,我试图写一个纯粹的node.js web服务器。 这个想法是完全避免使用预先编写的中间件或任何非默认的node.js模块来加载静态的HTML,CSS和JavaScript,并强迫自己学习所有的纯粹的node.js方法。

我已经启动并运行了几次,而且它似乎工作得很好,直到我决定通过几次静态页面快速刷新刷新来进行压力testing。

前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只是一个配对的扩展名及其适当的MIMEtypes的数组。

当存在HTML文件,CSS文件和JavaScript文件时,在加载页面期间,该函数将被调用三次。 再次,它工作正常,直到它突然没有。 那么,如果我再次刷新,一切都很好。

我怀疑发生了什么事,有时它会在CSS或JavaScript文件完成之前完成HTML文件。

我能想到的唯一解决方法是非常讨厌的。 我可以创build一个单独的函数来处理所有不是HTML的文件,并且让该进程保留剩余文件的数量。 然后,我可以在处理HTML的函数中使用while循环,并阻止它执行res.end()直到count为零,但这听起来既丑陋又可能导致资源枯竭。

或者我可以使用(甚至更糟糕的)解决方法同步加载所有非HTML文件,但由于该调用将来自其他asynchronous处理函数,我真的不想这样做。

如果我只是想build立一个静态网站,我会使用HTTP服务器或表示或许多优秀的解决scheme之一提供静态文件,但他们都有广泛的模块依赖,我试图得到这个没有他们做。

有没有一个优雅和纯粹的方式来确保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.css 因为“提供给客户”这两行都在底部,所以您知道您的节点服务器没有处理完第一个请求。 客户端收到的是app.js两次,作为.css和.js文件发送。

为什么是这样? 每个客户端请求命中节点服务器应理论上被隔离到它自己的事件循环。 不应该有交叉污染。 问题在于customServer.url ,这就是你分配传入的req.url值。 因为它不在两个客户端请求的范围之内,所以每个请求都会覆盖之前的值。

这不会是同步编程的问题,但是node.js是完全asynchronous的,并且将尽可能快地执行所有请求,无论是否有任何请求仍在等待处理。 您的fs.stat()调用需要一些时间来执行,并且在执行成功/错误callback之前很有可能会有另一个请求fs.stat()服务器。

tl; dr:这行 – customServer.getFile(customServer.url, res, ext); 将相同的文件发送到2个不同的请求,因为您正在用每个新的请求覆盖customServer.url跟踪请求范围内的请求URL!