You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Blazor中处理ASP.NET Core 10.0服务器发送事件(SSE)?

如何在Blazor中处理ASP.NET Core 10.0服务器发送事件(SSE)?

ASP.NET Core 10.0刚发布的时候,我就发现它新增了对服务器发送事件(SSE)的支持,刚好项目里需要实时推送数据,就折腾出了一套可行的方案——先是参考了官方示例,又结合了一个开源仓库的实现思路调整了细节。

我先把后端的SSE接口搭起来,用MinAPI写起来超简单,比如:

app.MapGet("/sse", async (HttpContext context) =>
{
    // 配置SSE必须的响应头
    context.Response.Headers.Append("Content-Type", "text/event-stream");
    context.Response.Headers.Append("Cache-Control", "no-cache");
    context.Response.Headers.Append("Connection", "keep-alive");

    var counter = 0;
    // 持续推送消息直到连接被主动取消
    while (!context.RequestAborted.IsCancellationRequested)
    {
        await context.Response.WriteAsync($"data: 实时推送消息 {++counter}\n\n");
        await context.Response.Body.FlushAsync();
        await Task.Delay(1000, context.RequestAborted);
    }
});

写完后端我先用curl测了下,执行curl http://localhost:5000/sse,确实能每隔一秒收到一条消息,说明后端的SSE服务是正常工作的。

接下来就是Blazor前端的处理了,因为Blazor本身没有原生的SSE客户端封装,所以得借助JavaScript互操作来实现:

第一步:在Blazor组件里添加SSE逻辑

我在组件里实现了IAsyncDisposable接口,用来在组件销毁时关闭SSE连接,避免内存泄漏:

@implements IAsyncDisposable
@inject IJSRuntime JS

<p>最新消息:@latestMessage</p>

@code {
    private string latestMessage = "等待推送...";
    private IJSObjectReference? sseUtilModule;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            // 导入JS模块
            sseUtilModule = await JS.InvokeAsync<IJSObjectReference>("import", "./js/sse-utils.js");
            // 初始化SSE连接
            await sseUtilModule.InvokeVoidAsync("setupSSE", "/sse", (Action<string>)HandleNewMessage);
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private void HandleNewMessage(string message)
    {
        latestMessage = message;
        // 通知组件更新UI
        StateHasChanged();
    }

    public async ValueTask DisposeAsync()
    {
        if (sseUtilModule is not null)
        {
            // 关闭SSE连接
            await sseUtilModule.InvokeVoidAsync("closeSSE");
            await sseUtilModule.DisposeAsync();
        }
    }
}

第二步:编写JS工具文件

在wwwroot/js目录下创建sse-utils.js,封装SSE的核心操作:

let eventSourceInstance;

export function setupSSE(url, messageCallback) {
    // 创建SSE连接实例
    eventSourceInstance = new EventSource(url);
    
    // 监听服务器推送的消息
    eventSourceInstance.onmessage = (event) => {
        messageCallback(event.data);
    };
    
    // 处理连接异常
    eventSourceInstance.onerror = (error) => {
        console.error("SSE连接出错:", error);
        closeSSE();
    };
}

export function closeSSE() {
    if (eventSourceInstance) {
        eventSourceInstance.close();
        eventSourceInstance = null;
    }
}

几个要注意的细节

  • 后端必须正确设置SSE的响应头,不然浏览器不会把响应识别为SSE流
  • 如果是Blazor WebAssembly项目,要记得在后端配置CORS,允许前端域名访问SSE接口
  • 一定要在组件销毁时关闭SSE连接,不然会造成不必要的资源浪费

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 12:28:16