NodeJS 讓我能夠用我最喜歡的語言之一編寫後端程式碼:JavaScript。它是構建即時應用程式的完美技術。在本教程中,我將向您展示如何使用 ExpressJS 和 Socket.io 建立網路聊天應用程式。
當然,首先要做的就是在您的系統上安裝 NodeJS。如果您是 Windows 或 Mac 用戶,可以造訪 nodejs.org 並下載安裝程式。如果您更喜歡 Linux,我建議您參考此連結。雖然我不會詳細介紹這一點,但如果您遇到任何安裝問題,我很樂意提供協助;只需在本文下方發表評論即可。
安裝 NodeJS 後,您就可以設定所需的工具了。
繼續,在空目錄中建立一個包含以下內容的 package.json 檔案。
{ "name": "RealTimeWebChat", "version": "0.0.0", "description": "Real time web chat", "dependencies": { "socket.io": "latest", "express": "latest", "jade": "latest" }, "author": "developer" }
透過使用控制台(在 Windows - 命令提示字元中),導航到您的資料夾並執行:
npm install
幾秒鐘之內,您就會將所有必要的依賴項下載到 node_modules 目錄中。
讓我們從一個簡單的伺服器開始,它將提供應用程式的 HTML 頁面,然後繼續更有趣的部分:即時通訊。使用以下核心expressjs程式碼建立一個index.js檔:
var express = require("express"); var app = express(); var port = 3700; app.get("/", function(req, res){ res.send("It works!"); }); app.listen(port); console.log("Listening on port " + port);
上面,我們創建了一個應用程式並定義了它的連接埠。接下來,我們註冊了一個路由,在本例中,它是一個不帶任何參數的簡單 GET 請求。目前,路由的處理程序只是向客戶端發送一些文字。最後,當然,在底部,我們運行伺服器。要初始化應用程序,請從控制台執行:
node index.js
伺服器正在運行,因此您應該能夠打開http://127.0.0.1:3700/並看到:
It works!
現在,我們應該提供 HTML,而不是「它有效」。使用模板引擎代替純 HTML 可能會更有益。 Jade 是一個很好的選擇,它與 ExpressJS 有很好的整合。這是我在自己的專案中通常使用的。建立一個名為 tpl 的目錄,並將以下 page.jade 檔案放入其中:
!!! html head title= "Real time web chat" body #content(style='width: 500px; height: 300px; margin: 0 0 20px 0; border: solid 1px #999; overflow-y: scroll;') .controls input.field(style='width:350px;') input.send(type='button', value='send')
Jade 的語法並不複雜,但是,要獲得完整的指南,我建議您參考jade-lang.com。為了將 Jade 與 ExpressJS 一起使用,我們需要進行以下設定。
app.set('views', __dirname + '/tpl'); app.set('view engine', "jade"); app.engine('jade', require('jade').__express); app.get("/", function(req, res){ res.render("page"); });
此程式碼通知 Express 您的範本檔案所在位置以及要使用的範本引擎。它全部指定將處理模板程式碼的函數。一旦一切設定完畢,我們就可以使用 response
物件的 .render
方法,並將我們的 Jade 程式碼傳送給使用者。
此時的輸出並不特殊;無非是一個div
元素(id 為content
的元素),它將用作聊天訊息的容器和兩個控制項(輸入欄位和按鈕),我們將使用它們來發送訊息。 p>
因為我們將使用一個外部 JavaScript 檔案來保存前端邏輯,所以我們需要通知 ExpressJS 在哪裡尋找此類資源。建立一個空目錄 public
,並在呼叫 .listen
方法之前新增以下行。
app.use(express.static(__dirname + '/public'));
到目前為止一切順利;我們有一個成功回應 GET 請求的伺服器。現在,是時候添加 Socket.io 整合了。更改此行:
app.listen(port);
至:
var io = require('socket.io').listen(app.listen(port));
上面,我們將 ExpressJS 伺服器傳遞給了 Socket.io。實際上,我們的即時通訊仍然會發生在同一連接埠上。
接下來,我們需要編寫從客戶端接收訊息並將其發送給所有其他客戶端的程式碼。每個 Socket.io 應用程式都以 connection
處理程序開始。我們應該有一個:
io.sockets.on('connection', function (socket) { socket.emit('message', { message: 'welcome to the chat' }); socket.on('send', function (data) { io.sockets.emit('message', data); }); });
傳遞給處理程序的物件 socket
其實是客戶端的套接字。將其視為伺服器和使用者瀏覽器之間的連接點。連接成功後,我們發送 welcome
類型的訊息,當然,也會綁定另一個將用作接收器的處理程序。結果,客戶端應該發出一條名為 send
的訊息,我們將捕獲該訊息。接下來,我們只需使用 io.sockets.emit
將使用者傳送的資料轉送到所有其他套接字。
透過上面的程式碼,我們的後端已準備好向客戶端接收和發送訊息。讓我們來添加一些前端程式碼。
建立 chat.js
,並將其放置在應用程式的 public
目錄中。貼上以下程式碼:
window.onload = function() { var messages = []; var socket = io.connect('http://localhost:3700'); var field = document.getElementById("field"); var sendButton = document.getElementById("send"); var content = document.getElementById("content"); socket.on('message', function (data) { if(data.message) { messages.push(data.message); var html = ''; for(var i=0; i<messages.length; i++) { html += messages[i] + '<br />'; } content.innerHTML = html; } else { console.log("There is a problem:", data); } }); sendButton.onclick = function() { var text = field.value; socket.emit('send', { message: text }); }; }
我们的逻辑包装在 .onload
处理程序中,只是为了确保所有标记和外部 JavaScript 均已完全加载。在接下来的几行中,我们创建一个数组,它将存储所有消息、一个 socket
对象以及一些 DOM 元素的快捷方式。同样,与后端类似,我们绑定一个函数,它将对套接字的活动做出反应。在我们的例子中,这是一个名为 message
的事件。当此类事件发生时,我们期望收到一个对象,data,其属性为 message
。将该消息添加到我们的存储中并更新 content
div
。我们还包含了发送消息的逻辑。这非常简单,只需发出一条名为 send 的消息。
如果你打开http://localhost:3700,你会遇到一些错误弹出窗口。这是因为我们需要更新 page.jade
以包含必要的 JavaScript 文件。
head title= "Real time web chat" script(src='/chat.js') script(src='/socket.io/socket.io.js')
请注意,Socket.io 管理 socket.io.js 的交付。您不必担心手动下载此文件。
我们可以在控制台中使用 node index.js
再次运行我们的服务器并打开http://localhost:3700。您应该会看到欢迎消息。当然,如果你发送一些东西,应该显示在内容的div
中。如果您想确保它有效,请打开一个新选项卡(或者更好的是,一个新浏览器)并加载应用程序。 Socket.io 的伟大之处在于,即使您停止 NodeJS 服务器它也能工作。前端将继续工作。一旦服务器再次启动,您的聊天也会正常。
在目前的状态下,我们的聊天并不完美,需要一些改进。
我们需要做的第一个更改是消息的标识。目前,尚不清楚哪些消息是由谁发送的。好处是我们不必更新 NodeJS 代码来实现这一点。这是因为服务器只是转发 data
对象。因此,我们需要在那里添加一个新属性,并稍后读取它。在对 chat.js
进行更正之前,让我们添加一个新的 input
字段,用户可以在其中添加他/她的姓名。在 page.jade
中,更改 controls
div
:
.controls | Name: input#name(style='width:350px;') br input#field(style='width:350px;') input#send(type='button', value='send')
接下来,在code.js中:
window.onload = function() { var messages = []; var socket = io.connect('http://localhost:3700'); var field = document.getElementById("field"); var sendButton = document.getElementById("send"); var content = document.getElementById("content"); var name = document.getElementById("name"); socket.on('message', function (data) { if(data.message) { messages.push(data); var html = ''; for(var i=0; i<messages.length; i++) { html += '<b>' + (messages[i].username ? messages[i].username : 'Server') + ': </b>'; html += messages[i].message + '<br />'; } content.innerHTML = html; } else { console.log("There is a problem:", data); } }); sendButton.onclick = function() { if(name.value == "") { alert("Please type your name!"); } else { var text = field.value; socket.emit('send', { message: text, username: name.value }); } }; }
为了总结这些变化,我们:
input
字段添加了新快捷方式username
属性,该属性将发送到服务器如果消息数量过多,用户将需要滚动 div
:
content.innerHTML = html; content.scrollTop = content.scrollHeight;
请记住,上述解决方案可能不适用于 IE7 及更低版本,但没关系:IE7 是时候消失了。但是,如果您想确保支持,请随意使用 jQuery:
$("#content").scrollTop($("#content")[0].scrollHeight);
如果发送消息后输入字段被清除,那就太好了:
socket.emit('send', { message: text, username: name.value }); field.value = "";
最后一个无聊的问题是每次点击发送按钮。通过一点 jQuery,我们可以监听用户何时按下 Enter
键。
$(document).ready(function() { $("#field").keyup(function(e) { if(e.keyCode == 13) { sendMessage(); } }); });
可以注册函数 sendMessage
,如下所示:
sendButton.onclick = sendMessage = function() { ... };
请注意,这不是最佳实践,因为它注册为全局函数。但是,对于我们在这里的小测试来说,一切都很好。
NodeJS 是一项非常有用的技术,它为我们提供了巨大的力量和乐趣,特别是考虑到我们可以编写纯 JavaScript 的事实。正如您所看到的,仅用几行代码,我们就编写了一个功能齐全的实时聊天应用程序。非常整洁!
想要了解有关使用 ExpressJS 构建 Web 应用程序的更多信息?我们为您服务!
以上是使用NodeJS、Socket.io和ExpressJS進行即時聊天的詳細內容。更多資訊請關注PHP中文網其他相關文章!