Websocket实时更新商品信息

产品展示页面中第一次通过接口去获取数据库的列表数据

/// <summary>

/// 获取指定的商品目录

/// </summary>

/// <param name="pageSize"></param>

/// <param name="pageIndex"></param>

/// <param name="ids"></param>

/// <returns></returns>

[HttpGet]

[Route("items")]

[ProducesResponseType(typeof(PaginatedViewModel<Catalog>), StatusCodes.Status200OK)]

[ProducesResponseType(typeof(IEnumerable<ProductDto>), StatusCodes.Status200OK)]

[ProducesResponseType(StatusCodes.Status400BadRequest)]

public async Task<IActionResult> Catalogs([FromQuery] int pageSize = 10, [FromQuery] int pageIndex = 0, string ids = null)

{

if (!string.IsNullOrEmpty(ids))

{

var items = await GetItemByIds(ids);

if (!items.Any())

{

return BadRequest("ids value invalid. Must be comma-separated list of numbers");

}

return Ok(items);

}

var totalItems = await _catalogContext.Catalogs

.LongCountAsync();

var itemsOnPage = await _catalogContext.Catalogs

.OrderBy(c => c.Name)

.Skip(pageSize * pageIndex)

.Take(pageSize)

.ToListAsync();

var result = itemsOnPage.Select(x => new ProductDto(x.Id.ToString(), x.Name, x.Price.ToString(), x.Stock.ToString(), x.ImgPath));

var model = new PaginatedViewModel<ProductDto>(pageIndex, pageSize, totalItems, result);

return Ok(model);

}

2.在前端页面会把当前页面的产品列表id都发送到websocket中去

function updateAndSendProductIds(ids) {
    productIds = ids;
 
    // Check if the WebSocket is open
    if (socket.readyState === WebSocket.OPEN) {
        // Send the list of product IDs through the WebSocket connection
        socket.send(JSON.stringify(productIds));
    }
}
 
function fetchData() {
    
    const apiUrl = baseUrl + `/Catalog/items?pageSize=${pageSize}&pageIndex=${currentPage}`;
 
    axios.get(apiUrl)
        .then(response => {
            const data = response.data.data;
            displayProducts(baseUrl, data);
 
            const newProductIds = data.map(product => product.Id);
            // Check if the WebSocket is open
            updateAndSendProductIds(newProductIds);
            // 从响应中获取总页数
            const totalPages = Math.ceil(response.data.count / pageSize);
            displayPagination(totalPages);
 
            // 更新当前页数的显示
            const currentPageElement = document.getElementById('currentPage');
            currentPageElement.textContent = `当前页数: ${currentPage + 1} / 总页数: ${totalPages}`;
        })
        .catch(error => {
            console.error('获取数据失败:', error);
        });
}

using System.Net.WebSockets;
using System.Threading.Tasks;
using System;
using WsServer.Handler;
using WsServer.Manager;
using StackExchange.Redis;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using Catalogs.Domain.Catalogs;
using Catalogs.Domain.Dtos;
using System.Net.Sockets;
 
namespace WebScoket.Server.Services
{
    /// <summary>
    /// 实时推送产品主要是最新的库存,其他信息也会更新
    /// </summary>
    public class ProductListHandler : WebSocketHandler
    {
        private System.Threading.Timer _timer;
        private readonly IDatabase _redisDb;
        //展示列表推送
        private string productIdsStr;
        public ProductListHandler(WebSocketConnectionManager webSocketConnectionManager,IConfiguration configuration) : base(webSocketConnectionManager)
        {
            ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(configuration["DistributedRedis:ConnectionString"] ?? throw new Exception("$未能获取distributedredis连接字符串"));
            _redisDb = redis.GetDatabase();
            _timer = new System.Threading.Timer(Send, null, TimeSpan.Zero, TimeSpan.FromSeconds(1));
        }
        private void Send(object state)
        {
            // 获取当前时间并发送给所有连接的客户端
            if (productIdsStr != null)
            {
                string[] productIds = System.Text.Json.JsonSerializer.Deserialize<string[]>(productIdsStr);
                string hashKeyToRetrieve = "products";
                List<ProductDto> products = new List<ProductDto>();
 
                foreach (var productId in productIds)
                {
                    if(productId == "null") {
                        continue;
                    }
                    string retrievedProductValue = _redisDb.HashGet(hashKeyToRetrieve, productId);
                    if (!string.IsNullOrEmpty(retrievedProductValue))
                    {
                        //反序列化和构造函数冲突,改造了一下Catalog
                        Catalog catalog = System.Text.Json.JsonSerializer.Deserialize<Catalog>(retrievedProductValue);
                        products.Add(new ProductDto(catalog.Id.ToString(), catalog.Name, catalog.Price.ToString(), catalog.Stock.ToString(), catalog.ImgPath));
                    }
                }
                if (products.Count > 0)
                {
                     SendMessageToAllAsync(System.Text.Json.JsonSerializer.Serialize(products)).Wait();
                }
                else
                {
                    SendMessageToAllAsync("NoProduct").Wait();
                }
            }
        }
        public override async Task ReceiveAsync(WebSocket socket, WebSocketReceiveResult result, byte[] buffer)
        {
            //每次页面有刷新就会拿到展示的id列表
            productIdsStr = System.Text.Encoding.UTF8.GetString(buffer, 0, result.Count);
        }
    }
}
相关推荐
EasyDSS36 分钟前
国标GB28181-2022平台EasyGBS:安防监控中P2P的穿透方法
网络协议·php·音视频·p2p
网安墨雨1 小时前
常用网络协议
网络·网络协议
Tlzns1 小时前
Linux网络——UDP的运用
linux·网络·udp
黑客老陈1 小时前
新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
运维·服务器·前端·网络·安全·web3·xss
HSunR3 小时前
计算机网络
网络·计算机网络
ZoeLandia3 小时前
WebSocket | 背景 概念 原理 使用 优缺点及适用场景
网络·websocket·网络协议
南七澄江3 小时前
各种网站(学习资源及其他)
开发语言·网络·python·深度学习·学习·机器学习·ai
Crossoads7 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
诸葛悠闲7 小时前
SOME/IP 协议详解——信息格式
网络协议
gywl10 小时前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos