在本教程中,我將向您展示如何使用 node.JS、socket.io 和 mongodb 實現一個實時聊天應用程序,然后我們將該應用程序一起部署到 modulus。
首先,讓我向您展示我們將在文章末尾看到的應用程序的最終外觀。
node.js 將成為應用程序的核心,express 作為 mvc,MongoDB 作為數據庫,Socket。 IO用于實時通信。完成后,我們將把應用程序部署到 Modulus。 MongoDB 部分實際上存在于 Modulus 內部。
1. 場景
- John 想要使用我們的應用程序,并在瀏覽器中打開它。
- 在第一頁上,他選擇聊天期間使用的昵稱,然后登錄聊天。
- 他在文本區域中寫了一些內容,然后按 Enter。
- 文本將發送至 restful 服務 (Express),并將該文本寫入 MongoDB。
- 在 MongoDB 中寫入之前,相同的文本將廣播給當前登錄聊天應用的用戶。
如您所見,這是一個非常簡單的應用程序,但它幾乎涵蓋了 Web 應用程序的所有內容。該應用程序中沒有頻道系統,但您可以fork源代碼并實現頻道模塊進行練習。
2.從頭開始進行項目設計
我將嘗試先解釋該項目的各個小部分,然后在最后將它們組合起來。我將從后端開始到前端。那么,讓我們從域對象(MongoDB 模型)開始。
2.1。型號
對于數據庫抽象,我們將使用 Mongoose。在這個項目中,我們只有一個模型,名為 Message。 這個消息模型只包含 text, createDate,?和 作者。 作者沒有像User這樣的模型,因為我們不會完全實現用戶注冊/登錄系統。將會有一個簡單的昵稱提供頁面,并且該昵稱將被保存到Cookie中。這將在 Message 模型中用作 author 字段中的文本。您可以在下面看到一個示例 json 模型:
{ text: "Hi, is there any Full Stack Developer here?" author: "john_the_full_stack", createDate: "2015.05.15" }
為了創建這樣的文檔,您可以使用下面的 Mongoose 函數來實現模型:
var mongoose = require('mongoose') var Message = new mongoose.Schema({ author: String, message: String, createDate: { type: Date, default: Date.now } }); mongoose.model('Message', Message)
只需導入 Mongoose 模塊,使用 JSON 格式的字段和字段屬性定義模型,然后創建名為 Message 的模型。該模型將包含在您要使用的頁面中。
也許您有疑問,當我們已經在同一頻道中向用戶廣播此消息時,為什么我們要將消息存儲在數據庫中。確實,您不必存儲聊天消息,但我只是想解釋一下數據庫集成層。不管怎樣,我們將在我們的項目中的控制器中使用這個模型。控制器?
2.2。控制器
正如我之前所說,我們將在 MVC 部分使用 Express。而C?這里代表的是Controller。對于我們的項目,只有兩個消息傳遞端點。其中之一是加載最近的聊天消息,第二個是處理發送的聊天消息存儲在數據庫中,然后廣播到頻道中。
..... app.get('/chat', function(req, res){ res.sendFile(__dirname + '/index.html'); }); app.get('/login', function(req, res){ res.sendFile(__dirname + '/login.html'); }); app.post('/messages', function(req, res, next) { var message = req.body.message; var author = req.body.author; var messageModel = new Message(); messageModel.author = author; messageModel.message = message; messageModel.save(function (err, result) { if (!err) { Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) { io.emit("message", messages); }); res.send("Message Sent!"); } else { res.send("Technical error occurred!"); } }); }); app.get('/messages', function(req, res, next) { Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) { res.json(messages); }); }); .....
第一個和第二個控制器僅用于為聊天和登錄頁面提供靜態 HTML 文件。第三個用于處理對 /messages? 端點的發布請求,以創建新消息。在該控制器中,首先將請求正文轉換為 Message 模型,然后使用 Mongoose 函數 save.??
我不會深入研究 Mongoose – 您可以查看文檔以了解更多詳細信息。你可以為save函數提供一個回調函數來檢查是否有問題。如果成功,我們將按 createDate 降序獲取最后 5 條記錄,并向頻道中的客戶端廣播 5 條消息。
好的,我們已經完成了 MC。?讓我們切換到 View 部分。
2.3。查看
一般來說,Express 中可以使用 Jade、EJS、Handlebars 等模板引擎。然而,我們只有一個頁面,那就是一條聊天消息,所以我將靜態地提供它。實際上,正如我上面所說,還有兩個控制器來服務這個靜態 HTML 頁面。您可以看到以下內容用于提供靜態 HTML 頁面。
app.get('/chat', function(req, res){ res.sendFile(__dirname + '/index.html'); }); app.get('/login', function(req, res){ res.sendFile(__dirname + '/login.html'); });
此端點僅使用 res.sendFile 提供 index.html 和 login.html。 ?index.html 和 login.html 與 server.js 位于同一文件夾中,這就是我們在 HTML 文件名之前使用 __dirname 的原因。
2.4。前端
在前端頁面中,我已經使用了bootstrap,無需解釋我是如何做到這一點的。簡單來說,我將一個函數綁定到一個文本框,每當您按下Enter鍵或發送按鈕時,消息就會發送到后端服務。
該頁面還有一個必需的Socket.IO js文件,用于監聽名為message的頻道。 Socket.IO 模塊已在后端導入,當您在服務器端使用此模塊時,它會自動添加一個端點來提供 Socket.IO js 文件,但我們使用由 cdn 。每當有新消息進入此頻道時,都會自動檢測到該消息,并且消息列表將刷新為最后 5 條消息。
<script> var socket = io(); socket.on("message", function (messages) { refreshMessages(messages); }); function refreshMessages(messages) { $(".media-list").html(""); $.each(messages.reverse(), function(i, message) { $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">' + message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.createDate + '<hr/>'); }); } $(function(){ if (typeof $.cookie("realtime-chat-nickname") === 'undefined') { window.location = "/login" } else { $.get("/messages", function (messages) { refreshMessages(messages) }); $("#sendMessage").on("click", function() { sendMessage() }); $('#messageText').keyup(function(e){ if(e.keyCode == 13) { sendMessage(); } }); } function sendMessage() { $container = $('.media-list'); $container[0].scrollTop = $container[0].scrollHeight; var message = $("#messageText").val(); var author = $.cookie("realtime-chat-nickname"); $.post( "/messages", {message: message, author: author}, function( data ) { $("#messageText").val("") }); $container.animate({ scrollTop: $container[0].scrollHeight }, "slow"); } }) </script>
上面的代碼中還有一項檢查:cookie 部分。如果您沒有選擇任何聊天昵稱,則表示該昵稱沒有設置cookie,您將自動重定向到登錄頁面。
如果沒有,最后五條消息將通過對 /messages 端點的簡單 ajax 調用來獲取。同樣,每當您點擊發送按鈕或按Enter鍵時,都會從文本框中提取短信,并從文本框中提取昵稱。 cookie,這些值將通過 post 請求發送到服務器。這里沒有嚴格檢查昵稱,因為我想關注實時部分,而不是用戶身份驗證部分。
正如你所看到的,項目的整體結構非常簡單。讓我們進入部署部分。正如我之前所說,我們將使用 Modulus,它是用您選擇的語言部署、擴展和監控應用程序的最佳 paas 之一。
3.部署
3.1。先決條件
我首先想到的是向您展示如何部署,但為了成功部署,我們需要一個工作數據庫。我們來看看如何在Modulus上創建數據庫,然后進行部署。
創建帳戶后轉至 Modulus 儀表板。點擊左側的數據庫菜單,然后點擊創建數據庫。
在彈出表單中填寫必填字段,如下所示。
當您填寫必填字段并點擊創建時,它將創建一個 MongoDB 數據庫您將在屏幕上看到您的數據庫 URL。我們將使用 MONGO URI,?因此請復制該 URI。
在我們的項目中,Mongo URI是從環境變量MONGO_URI中獲取的,您需要在儀表板中設置該環境變量。轉到信息中心,點擊項目菜單,在列表中選擇您的項目,然后點擊左側菜單中的管理。在此頁面中,向下滾動頁面時您將看到環境變量部分,如下所示。
您可以通過兩種方式部署到 Modulus:
- 使用儀表板上傳項目 ZIP 文件
- 使用 Modulus CLI 從命令行進行部署
我將繼續使用命令行選項,因為另一個很容易做到。首先,安裝 Modulus CLI:
npm install -g modulus
轉到您的項目文件夾并執行以下命令以登錄 Modulus。
modulus login
當您執行上述命令時,系統會提示您輸入用戶名和密碼:
如果您已使用 github 創建帳戶,則可以使用 –github 選項.
modulus login --github
現在您已登錄 Modulus,可以創建項目了。使用以下命令創建項目:
modulus project create "Realtime Chat"
當您運行此函數時,系統會詢問您運行時。選擇第一個選項,即 Node.js,第二個選項將詢問您伺服器的大小,您可以保留默認值。
我們已經創建了一個項目,這次我們將把當前項目部署到Modulus中。執行以下命令將當前項目發送到Modulus端的Realtime Chat項目中。
modulus deploy
它將部署您的項目,并且您將在成功部署消息的末尾獲得正在運行的項目 URL:
Realtime Chat running at realtime-chat-46792.onmodulus.net
如您所見,部署到 Modulus 非常簡單!
Modulus CLI 具有非常有用的命令,可在項目部署或運行??時使用。例如,為了跟蹤正在運行的項目的日志,您可以使用 modulus 項目日志 tail,創建 MongoDB 數據庫使用 modulus mongo create
結論
本教程的主要目的是向您展示如何使用 Node.js、Socket.IO 和 MongoDB 創建實時聊天應用程序。為了在生產中運行項目,Modulus 被用作 PaaS 提供商。 Modulus 的部署步驟非常簡單,而且它還為我們的項目提供了一個內部數據庫(MongoDB)。除此之外,您還可以在 Modulus 儀表板中使用非常有用的工具,例如日志、通知、自動縮放、數據庫管理等。
要注冊 Modulus,請點擊此處,成為 Tuts+ 讀者即可額外獲得 10 美元。使用促銷代碼ModulusChat10。
有關 Modulus 企業產品的更多信息,請點擊此處。