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

标签 javascript node.js

为了 self 完善,我正在尝试编写一个纯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 文件,并让该进程保留剩余文件的计数。然后我可以在处理 HTML 的函数中使用 while 循环,并阻止它执行 res.end() 直到计数为零,但这听起来既难看又可能资源耗尽。

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

如果我只是想构建一个静态站点,我会使用 http-server 或 express 或用于提供静态文件的众多优秀解决方案之一,但它们都具有广泛的模块依赖性,并且我正在尝试无需他们即可完成此任务。

有没有一种优雅而纯粹的方法来确保在所有非 HTML 文件完成其操作之前,加载的 HTML 不会发生 res.end()

编辑:所以任何人都可以看到整个上下文、整个项目及其内容,都在 github 上:https://github.com/GoodDamon/customserver

最佳答案

您的问题在于 customServer.url。如果您打开浏览器的开发工具并检查 app.css 的内容,您会发现偶尔只填充以下行:

console.log("CustomServer 成功加载!");

...这恰好与您的 app.js 文件的内容相同。巧合?没有。如果您查看 Node 控制台输出,您有时会看到以下内容:

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>。因为“提供给客户端”这两行都位于底部,所以您知道您的 Node 服务器尚未处理第一个请求。客户端最终收到的是 app.js 两次,以 .css 和 .js 文件形式发送。

这是为什么呢?理论上,到达 Node 服务器的每个客户端请求都应该与其自己的事件循环隔离。不应有交叉污染。问题在于 customServer.url,这是您将传入的 req.url 值分配给的内容。因为它位于两个客户端请求的范围之外,所以每个请求都会覆盖前一个请求的值。

这对于同步编程来说不是问题,但 Node.js 是完全异步的,并且会在收到请求后尽快执行所有请求,无论是否还有任何请求仍在等待处理。您的 fs.stat() 调用需要一些时间来执行,并且很有可能在执行成功/错误回调之前另一个请求已经到达服务器。

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

关于javascript - 自定义 Node.js Web 服务器未完成加载 CSS 和 JavaScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33070553/

相关文章:

javascript - 了解 <a href "javascript : ... ;"> 中的 =""

javascript - 如何加载 .js 文件 UIWebView

javascript - Node.js 服务器 "404 not found"消息到 404.html 页面

node.js - 在 Node 模块中处理 __dirname

node.js - 如果 Node 关闭,如何在多个 Node 上处理 socketio

javascript - 使用字符集 windows-1251 处理请求时出错

javascript - 访问 jquery 函数范围之外的 javascript 变量

javascript - 如何在 body 标签中插入 Before() 元素?

javascript - 哪个版本的 IE 使用 window[objectName] 而不是 window.document[objectName]?

javascript - 使用命令的数组