简体   繁体   English

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

[英]Custom node.js web server doesn't finish loading CSS and JavaScript

For self-betterment, I'm trying to write a pure node.js web server.为了自我完善,我正在尝试编写一个纯 node.js Web 服务器。 The idea is to completely avoid using pre-written middleware or any non-default node.js modules for loading static HTML, CSS, and JavaScript, and force myself to learn all of the ins and outs of doing it the purist node.js way.这个想法是完全避免使用预先编写的中间件或任何非默认的 node.js 模块来加载静态 HTML、CSS 和 JavaScript,并强迫自己学习所有的来龙去脉,以纯粹的 node.js 方式.

I've got it up and running, and tested it a few times, and it seemed to be working great until I decided to stress test it a bit by hitting refresh quickly on a static page a few times.我已经启动并运行它,并对其进行了几次测试,它似乎运行良好,直到我决定通过在静态页面上快速刷新几次来对其进行压力测试。

The first 3-4 reloads work fine.前 3-4 次重新加载工作正常。 After that, none of the CSS or JavaScript files called by the static HTML file load.之后,静态 HTML 文件调用的任何 CSS 或 JavaScript 文件都不会加载。

Here's my file reading code:这是我的文件读取代码:

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 is just an array of paired extensions and their appropriate mime types.) validExtensions只是一组配对的扩展及其适当的 mime 类型。)

This function will be called three times during a page load when there's the HTML file, a CSS file, and a JavaScript file.当有 HTML 文件、CSS 文件和 JavaScript 文件时,此函数将在页面加载期间调用 3 次。 Again, it works fine until it suddenly doesn't.再次,它工作正常,直到它突然没有。 Then, if I refresh once more, everything is fine again.然后,如果我再次刷新,一切都会再次好起来。

I suspect what's going on is that sometimes it finishes the HTML file before the CSS or JavaScript file has finished.我怀疑发生的事情是有时它在 CSS 或 JavaScript 文件完成之前完成了 HTML 文件。

The only workarounds I can think of are pretty nasty.我能想到的唯一解决方法是非常讨厌。 I could create a separate function for processing all files that aren't HTML, and having that process keep a count of the remaining files.我可以创建一个单独的函数来处理所有不是 HTML 的文件,并让该过程保持对剩余文件的计数。 Then I could use a while loop in the function that processes HTML and prevents it from doing res.end() until that count is zero, but that sounds both ugly and possibly resource-draining.然后我可以在处理 HTML 的函数中使用一个while循环并阻止它执行res.end()直到该计数为零,但这听起来既丑陋又可能消耗资源。

Or I could use the (even worse) workaround of loading all non-HTML files synchronously, but since that call would be from within an otherwise-asynchronously processing function, I really don't want to do that.或者我可以使用同步加载所有非 HTML 文件的(更糟糕的)解决方法,但由于该调用将来自其他异步处理函数,我真的不想这样做。

If I were just trying to build a static site, I'd use http-server or express or one of the many excellent solutions out there for serving static files, but they all have extensive module dependencies, and I'm trying to get this done without them.如果我只是想构建一个静态站点,我会使用 http-server 或 express 或许多优秀的解决方案之一来提供静态文件,但它们都具有广泛的模块依赖关系,我正在尝试使用它在没有他们的情况下完成。

Is there an elegant and purist way to ensure res.end() doesn't happen for the HTML being loaded until all non-HTML files are finished doing their things?有没有一种优雅而纯粹的方式来确保在所有非 HTML 文件完成它们的工作之前,加载的 HTML 不会发生res.end()

Edit : So anyone can see the entire context, the whole project, what there is of it, is up on github here: https://github.com/GoodDamon/customserver编辑:所以任何人都可以看到整个上下文,整个项目,它的内容,都在 github 上: https : //github.com/GoodDamon/customserver

Your issue lies with customServer.url .您的问题在于customServer.url If you were to open your browser's dev tools and examine the contents of app.css , you'd find that occasionally it gets populated with only the following line:如果您要打开浏览器的开发工具并检查app.css的内容,您会发现它偶尔会填充以下行:

console.log("CustomServer successfully loaded!");

...which happens to be the same as the contents of your app.js file. ...这恰好与您的app.js文件的内容相同。 Coincidence?巧合? Nope.不。 If you take a look at your node console output, from time to time you'll see this:如果您查看节点控制台输出,您会不时看到以下内容:

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.

As you can see, the browser is requesting app.css first, immediately followed by app.js .如您所见,浏览器首先请求app.css ,紧接着是app.js Because both "Providing to Client" lines are at the bottom, you know that your node server was not done processing the first request.因为“Providing to Client”两行都在底部,所以您知道您的节点服务器没有完成第一个请求的处理。 What the client ends up receiving is app.js twice, sent as both a .css and a .js file.客户端最终收到的是app.js两次,分别作为 .css 和 .js 文件发送。

Why is this?为什么是这样? Each client request that hits the node server should be theoretically be isolated to it's own event loop.每个到达节点服务器的客户端请求理论上都应该被隔离到它自己的事件循环中。 There should be no cross-contamination.不应有交叉污染。 The issue lies with customServer.url , which is what you are assigning the incoming req.url values to.问题在于customServer.url ,这是您将传入的req.url值分配给的req.url Because it lies outside the scope of both client requests, every request overwrites the value of the previous.因为它位于两个客户端请求的范围之外,所以每个请求都会覆盖前一个请求的值。

This would not be an issue with synchronous programming, but node.js is completely async and will execute all requests as fast as it receives them, regardless if there are any requests still pending.这不会是同步编程的问题,但 node.js 是完全异步的,并且会在收到请求时尽快执行所有请求,无论是否有任何请求未决。 Your fs.stat() call takes a bit of time to execute and there's a good chance that another request will have hit the server before the success/error callback is executed.您的fs.stat()调用需要一些时间来执行,并且很有可能在执行成功/错误回调之前另一个请求已经命中服务器。

tl;dr: This line- customServer.getFile(customServer.url, res, ext); tl; dr:这一行 - customServer.getFile(customServer.url, res, ext); sends the same file to 2 different requests because you are overwriting customServer.url with every new request.将相同的文件发送到 2 个不同的请求,因为您正在使用每个新请求覆盖customServer.url Track your request URL within the scope of the request!在请求范围内跟踪您的请求 URL!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM