目:Socket.IO 環(huán)境搭建與實(shí)時(shí)通信入門(Set up the Environment 挑戰(zhàn)詳解))
freeCodeCamp Advanced Node and Express 項(xiàng)目Socket.IO 環(huán)境搭建與實(shí)時(shí)通信入門Set up the Environment 挑戰(zhàn)詳解【免費(fèi)下載鏈接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇基于 freeCodeCamp 課程庫(kù)中「Advanced Node and Express」項(xiàng)目里的Set up the Environment挑戰(zhàn)文檔展開。讀完后你不僅會(huì)掌握將 Socket.IO 掛接到已鑒權(quán)的 Express 應(yīng)用GitHub 社交登錄 Passport上的完整步驟還能理解該挑戰(zhàn)在課程結(jié)構(gòu)中的定位、challengeType: 2backend挑戰(zhàn)的測(cè)試判定機(jī)制以及五條自動(dòng)校驗(yàn)規(guī)則的具體實(shí)現(xiàn)。挑戰(zhàn)在課程中的定位該挑戰(zhàn)文檔位于 advanced-node-and-express 挑戰(zhàn)目錄是「Advanced Node and Express」這個(gè)大型后端項(xiàng)目的第 18 個(gè)挑戰(zhàn)也是該項(xiàng)目中Socket.IO 實(shí)時(shí)通信階段的起點(diǎn)。從 block 結(jié)構(gòu)文件 的challengeOrder可以確認(rèn)它的上下文位置前置挑戰(zhàn)Implementation of Social Authentication III實(shí)現(xiàn) GitHub 社交登錄對(duì)應(yīng) id589a8eb3f9fc0f352b528e72——也就是說(shuō)開始本挑戰(zhàn)時(shí)你的應(yīng)用已經(jīng)具備 Passport 的 GitHub 策略、ensureAuthenticated中間件和 GitHub 回調(diào)路由后繼挑戰(zhàn)依次為Communicate by Emitting、Handle a Disconnect、Authentication with Socket.IO、Announce New Users、Send and Display Chat Messages。本挑戰(zhàn)搭建的/chat頁(yè)面與socket.io環(huán)境正是這五個(gè)挑戰(zhàn)共同依賴的基座。整個(gè) block 歸屬于 Quality Assurance 超級(jí)模塊advanced-node-and-express是其三個(gè) block 之一。此外該挑戰(zhàn) front matter 中聲明challengeType: 2。對(duì)照課程共享包中的類型定義 challenge-types.ts2即backend類型其viewTypes映射為backend、submitTypes映射為backend——這意味著該挑戰(zhàn)在學(xué)員端以后端項(xiàng)目視圖呈現(xiàn)提交后測(cè)試代碼會(huì)直接訪問(wèn)項(xiàng)目?jī)?nèi)文件/_api/server.js等做正則斷言而不是在瀏覽器中運(yùn)行前端斷言。第一步添加 /chat 路由并改造 GitHub 回調(diào)挑戰(zhàn)文檔給出的原始要求是后續(xù)挑戰(zhàn)都會(huì)用到chat.pug文件。因此需要在routes.js中添加一條指向/chat的 GET 路由該路由使用ensureAuthenticated中間件并渲染chat.pug同時(shí)把{ user: req.user }作為響應(yīng)參數(shù)傳入模板router.get(/chat, ensureAuthenticated, (req, res) { res.render(chat, { user: req.user }); });接著修改已有的/auth/github/callback路由設(shè)置req.session.user_id req.user.id并重定向到/chat。這樣登錄完成后用戶會(huì)自動(dòng)進(jìn)入聊天頁(yè)且會(huì)話中保存了數(shù)據(jù)庫(kù)用戶 id為后續(xù)「Socket.IO 鑒權(quán)」挑戰(zhàn)做鋪墊。第二步用 http.createServer 掛載 Express 并實(shí)例化 Socket.IO文檔說(shuō)明socket.io~2.3.0已作為依賴添加需要在服務(wù)端按如下方式引入——注意 Socket.IO 的服務(wù)器端必須綁定在一個(gè)原生http服務(wù)器上而不是直接掛在 Express 應(yīng)用上const http require(http).createServer(app); const io require(socket.io)(http);這里有兩點(diǎn)值得展開http.createServer(app)將 Express 應(yīng)用作為請(qǐng)求處理器掛到 Node.js 內(nèi)置http模塊創(chuàng)建的服務(wù)器實(shí)例上使 Express 繼續(xù)處理普通 HTTP 請(qǐng)求require(socket.io)(http)返回的io實(shí)例則附加在同一http服務(wù)器上負(fù)責(zé) WebSocket 長(zhǎng)連接的管理。兩者共用同一個(gè)端口和同一個(gè)http實(shí)例因此必須把原來(lái)app.listen那一行改為http.listen——因?yàn)?Express 本身不直接監(jiān)聽端口真正的監(jiān)聽者變成了包裹了它的http服務(wù)器。第三步監(jiān)聽連接事件io.on(connection, ...)Socket.IO 基于事件模型on關(guān)鍵字用于監(jiān)聽特定事件它接收兩個(gè)參數(shù)——事件名字符串和事件觸發(fā)時(shí)執(zhí)行的處理函數(shù)。對(duì)「新連接」這一事件而言第二個(gè)參數(shù)約定命名為socket它代表一個(gè)獨(dú)立已連接的客戶端io.on(connection, socket { console.log(A user has connected); });文檔要求在數(shù)據(jù)庫(kù)連接建立之后加入這段監(jiān)聽代碼。加載應(yīng)用并完成鑒權(quán)登錄后服務(wù)端控制臺(tái)應(yīng)打印A user has connected這是本階段的第一次運(yùn)行驗(yàn)證。第四步客戶端連接對(duì)客戶端而言連接代碼只有兩行添加到鑒權(quán)頁(yè)面加載的client.js中/*global io*/ let socket io();/*global io*/是 JSHint 風(fēng)格的注釋聲明用于抑制「io未定義」的 lint 報(bào)錯(cuò)——因?yàn)閕o全局對(duì)象由chat.pug頁(yè)面中通過(guò)可靠 CDN 引入的 Socket.IO 客戶端庫(kù)提供無(wú)參調(diào)用io()只適用于連接同 URL/同服務(wù)器上托管的 Socket.IO 服務(wù)若要連接部署在其他位置的 Socket.IO 服務(wù)器則需顯式寫出地址io.connect(URL);。自動(dòng)校驗(yàn)規(guī)則五條 Hint 測(cè)試逐條解析該挑戰(zhàn)屬于backend類型提交后測(cè)試代碼會(huì)通過(guò)fetch讀取項(xiàng)目文件并做正則斷言。文檔中定義的# --hints--部分包含 5 條斷言它們精確刻畫了本挑戰(zhàn)的「正確實(shí)現(xiàn)」邊界1.socket.io必須出現(xiàn)在依賴中——測(cè)試讀取/_api/package.jsonconst url new URL(/_api/package.json, code); const res await fetch(url); const packJson await res.json(); assert.property( packJson.dependencies, socket.io, Your project should list socket.io as a dependency );2. 必須正確 require 內(nèi)置http模塊——讀取/_api/server.js用成對(duì)引號(hào)反向引用\1保證 require 字符串與變量一致const url new URL(/_api/server.js, code); const res await fetch(url); const data await res.text(); assert.match( data, /http.*.*require.*(|)http\1/s, Your project should list http as a dependency );3.socket.io必須以http為參數(shù)實(shí)例化為io——正則要求io、require(socket.io)、http三者按序出現(xiàn)assert.match( data, /io.*.*require.*(|)socket.io\1.*http/s, You should correctly require and instantiate socket.io as io. );4. 服務(wù)端必須監(jiān)聽connection事件且第二參變量名為socketassert.match( data, /io.on.*(|)connection\1.*socket/s, io should listen for connection and socket should be the 2nd arguments variable );5. 客戶端必須以socket為變量名完成連接——讀取/_public/client.jsconst url new URL(/public/client.js, code); const res await fetch(url); const data await res.text(); assert.match( data, /socket.*.*io/s, Your client should be connection to server with the connection defined as socket );從這些斷言可以看出課程設(shè)計(jì)的約束粒度不僅要求功能可用還要求變量命名http、io、socket與官方教程一致便于后續(xù)挑戰(zhàn)的代碼模式保持一致。機(jī)制溯源挑戰(zhàn)文檔如何變成可運(yùn)行的課程數(shù)據(jù)從倉(cāng)庫(kù)工程角度看這類挑戰(zhàn)是「Markdown 課程文檔 結(jié)構(gòu)化 front matter」的產(chǎn)物front matter 提供id、title、challengeType、forumTopicId、dashedName等元數(shù)據(jù)正文中的# --description--段落作為學(xué)員看到的題目描述# --hints--段落按「一句提示語(yǔ) 一個(gè) js 代碼塊」成對(duì)出現(xiàn)即測(cè)試斷言。解析入口位于 challenge-parser 解析器而字段的合法性則由 challenge-schema.js 以 Joi 校驗(yàn)。dashedName本文檔為set-up-the-environment用于生成 URL 友好的錨點(diǎn)例如后續(xù)挑戰(zhàn)中「查看已完成項(xiàng)目」的論壇鏈接即按#set-up-the-environment定位討論帖。下一步從「能連上」到「能通信」本挑戰(zhàn)的終點(diǎn)是控制臺(tái)打印A user has connected。緊接著的下一挑戰(zhàn) Communicate by Emitting 將在本挑戰(zhàn)搭好的connection監(jiān)聽器基礎(chǔ)上引入io.emit(user count, currentUsers)廣播用戶數(shù)事件客戶端則用socket.on(user count, ...)接收——即從「建立連接」推進(jìn)到「雙向事件通信」并最終串聯(lián)出完整的實(shí)時(shí)聊天室功能。小結(jié)/chat路由 ensureAuthenticatedchat.pug渲染是 Socket.IO 階段的頁(yè)面基座GitHub 回調(diào)中寫入req.session.user_id并重定向/chat為后續(xù) Socket 層鑒權(quán)埋下伏筆http.createServer(app)require(socket.io)(http)http.listen是 Express 應(yīng)用接入 Socket.IO 的標(biāo)準(zhǔn)三步io.on(connection, socket ...)與服務(wù)端let socket io()構(gòu)成最小可用的連接閉環(huán)五條 hint 測(cè)試以正則斷言鎖定了依賴聲明、變量命名與事件監(jiān)聽的實(shí)現(xiàn)細(xì)節(jié)這也是 freeCodeCampbackend類挑戰(zhàn)challengeType: 2的典型驗(yàn)收方式?!久赓M(fèi)下載鏈接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考