[英]Custom node.js web server doesn't finish loading CSS and JavaScript
為了自我完善,我正在嘗試編寫一個純 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 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
。 因為“Providing to Client”兩行都在底部,所以您知道您的節點服務器沒有完成第一個請求的處理。 客戶端最終收到的是app.js
兩次,分別作為 .css 和 .js 文件發送。
為什么是這樣? 每個到達節點服務器的客戶端請求理論上都應該被隔離到它自己的事件循環中。 不應有交叉污染。 問題在於customServer.url
,這是您將傳入的req.url
值分配給的req.url
。 因為它位於兩個客戶端請求的范圍之外,所以每個請求都會覆蓋前一個請求的值。
這不會是同步編程的問題,但 node.js 是完全異步的,並且會在收到請求時盡快執行所有請求,無論是否有任何請求未決。 您的fs.stat()
調用需要一些時間來執行,並且很有可能在執行成功/錯誤回調之前另一個請求已經命中服務器。
tl; dr:這一行 - customServer.getFile(customServer.url, res, ext);
將相同的文件發送到 2 個不同的請求,因為您正在使用每個新請求覆蓋customServer.url
。 在請求范圍內跟蹤您的請求 URL!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.