在现代 Web 应用中,我们经常需要构建实时更新的功能,比如在线聊天室、实时通知和在线书城等。为了实现这些功能,我们可以使用不同的技术,比如 Websockets、AJAX 长轮询和 Server-Sent Events(SSE)。在本文中,我们将重点介绍如何使用 SSE 技术构建实时在线书城应用。
什么是 Server-Sent Events
SSE 是一种 HTML5 技术,它允许服务器向客户端推送实时数据流。与 Websockets 不同,SSE 使用了标准的 HTTP 协议,客户端通过建立持久化的 HTTP 连接来接收服务器推送的事件。SSE 通常用于推送实时数据、服务器发送的通知和更新以及在线聊天等应用场景。
在线书城应用架构
为了演示如何使用 SSE 构建实时在线书城应用,我们需要先了解一下应用的基本架构。
在线书城应用通常包含以下几个组件:
服务器:负责处理用户请求和推送事件到客户端,通常使用 Node.js 或其他服务器端技术实现。
数据库:存储书籍和其他相关信息,通常使用 MySQL、MongoDB 或其他数据库。
客户端:展示书籍列表和书籍详情,以及接收实时推送的书籍更新事件。通常使用 HTML、CSS 和 JavaScript 实现。
在本文中,我们将使用 Node.js 和 MongoDB 实现服务器端和数据库,并使用 SSE 技术实现客户端和服务器端之间的实时通信。
服务器端实现
在服务器端,我们需要使用 Node.js 和 Express 框架实现 HTTP API 和 SSE 服务。以下是服务器端的基本实现:
// javascriptcn.com 代码示例 const express = require('express') const mongoose = require('mongoose') const Book = require('./models/book') const app = express() const port = 3000 // 连接 MongoDB 数据库 mongoose.connect('mongodb://localhost/bookstore', { useNewUrlParser: true, useUnifiedTopology: true }) // HTTP API 获取书籍列表 app.get('/books', async (req, res) => { const books = await Book.find() res.json(books) }) // SSE 服务推送书籍更新事件 app.get('/books/events', async (req, res) => { res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }) const stream = Book.watch() stream.on('change', (change) => { const book = change.fullDocument res.write(`event: update\ndata: ${JSON.stringify(book)}\n\n`) }) }) app.listen(port, () => { console.log(`Server listening on port ${port}`) })
上述代码中,我们定义了两个路由 /books
和 /books/events
,分别用于 HTTP API 和 SSE 服务。
/books
路由使用 MongoDB 的 find
方法查询书籍列表,并返回 JSON 格式的数据。
/books/events
路由使用 MongoDB 的 watch
方法监听书籍集合的变化,并通过 SSE 服务向客户端推送书籍更新事件。在每次变化时,我们将书籍更新数据作为 JSON 格式的数据传递给客户端,其中 event: update
表示事件类型为更新事件。
客户端实现
在客户端,我们需要使用 JavaScript 实现 SSE 接收和处理书籍更新事件。以下是客户端的基本实现:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>在线书城</title> </head> <body> <h1>在线书城</h1> <h2>书籍列表</h2> <table id="book-list"> <thead> <tr> <th>ID</th> <th>书名</th> <th>作者</th> <th>价格</th> </tr> </thead> <tbody> <tr> <td colspan="4">加载中...</td> </tr> </tbody> </table> <h2>书籍详情</h2> <div id="book-detail"></div> <script> const bookList = document.getElementById('book-list') const bookDetail = document.getElementById('book-detail') // SSE 接收书籍更新事件 const source = new EventSource('/books/events') source.addEventListener('update', event => { const book = JSON.parse(event.data) // 更新书籍列表 const row = bookList.querySelector(`tr[data-id="${book._id}"]`) if (row) { row.innerHTML = ` <td>${book._id}</td> <td>${book.title}</td> <td>${book.author}</td> <td>${book.price}</td> ` } else { const newRow = document.createElement('tr') newRow.dataset.id = book._id newRow.innerHTML = ` <td>${book._id}</td> <td>${book.title}</td> <td>${book.author}</td> <td>${book.price}</td> ` bookList.querySelector('tbody').appendChild(newRow) } // 更新书籍详情 if (bookDetail.dataset.id === book._id) { bookDetail.innerHTML = ` <h3>${book.title}</h3> <p>${book.author}</p> <p>${book.price}</p> ` } }) // HTTP 获取书籍列表和书籍详情 fetch('/books') .then(response => response.json()) .then(books => { bookList.querySelector('tbody').innerHTML = '' books.forEach(book => { const row = document.createElement('tr') row.dataset.id = book._id row.innerHTML = ` <td>${book._id}</td> <td>${book.title}</td> <td>${book.author}</td> <td>${book.price}</td> ` bookList.querySelector('tbody').appendChild(row) }) const firstBook = books[0] if (firstBook) { bookDetail.dataset.id = firstBook._id bookDetail.innerHTML = ` <h3>${firstBook.title}</h3> <p>${firstBook.author}</p> <p>${firstBook.price}</p> ` } }) </script> </body> </html>
上述代码中,我们使用 HTML 和 CSS 构建了一个简单的书城页面,并使用 JavaScript 实现了 SSE 接收和处理书籍更新事件。
在客户端通过 new EventSource('/books/events')
创建 SSE 连接,并指定事件类型为 update
。在 update
事件被触发时,我们通过解析事件的数据,更新书籍列表和书籍详情。如果书籍列表中已存在被更新的书籍,则更新其数据行,否则创建一行数据行。如果当前书籍详情为被更新的书籍,则更新书籍详情显示的数据。
同时,我们通过 HTTP 请求获取书籍列表和书籍详情,并在页面加载完成时显示默认的书籍详情。
总结
本文中,我们介绍了如何使用 SSE 技术构建实时在线书城应用。通过使用 Node.js 和 Express 实现服务器端和 MongoDB 实现数据库,以及使用 HTML、CSS 和 JavaScript 实现客户端,我们成功地实现了一个简单的在线书城应用,并演示了如何使用 SSE 技术进行实时通信和响应。使用 SSE 技术可以极大地提升 Web 应用的实时性和交互性,适用于许多不同的应用场景。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654a27317d4982a6eb44e792