- 添加SignalR服务
builder.Services.AddSignalR(configure =>
{
configure.ClientTimeoutInterval = TimeSpan.FromMinutes(3);
configure.KeepAliveInterval = TimeSpan.FromMinutes(1);
});
- 创建自己的Hub
// 这里的hub是空的,是因为不需要客户端调用服务端,我们只实现SSE,既服务端向客户端发送通知
public class NotificationHub : Hub
{
}
- 创建通知服务并添加到容器中
public class NotificationMessage
{
public string Type { get; set; } = null!;
public object? Data { get; set; } = null!;
}
public interface INotificationService
{
Task SendMessageAsync(NotificationMessage message);
}
public class NotificationService(IHubContext<NotificationHub> context) : INotificationService
{
public async Task SendMessageAsync(NotificationMessage message)
{
await context.Clients.All.SendAsync("ReceiveMessage", JsonConvert.SerializeObject(message));
}
}
builder.Services.AddScoped<INotificationService, NotificationService>();
- 将Hub配置到请求管道
app.MapHub<NotificationHub>("/api/notificationhub");
- 使用vue接收通知
import { HubConnectionBuilder, LogLevel, HttpTransportType } from '@microsoft/signalr'
import { defineStore } from "pinia"
import { onMounted, ref } from 'vue'
export const useNotificationStore = defineStore('notification', () => {
const funcs = ref([])
onMounted(() => {
initialize()
})
function initialize() {
const connection = new HubConnectionBuilder()
.withKeepAliveInterval(60000)
.withServerTimeout(180000)
.withUrl("/api/notificationhub", {
transport: HttpTransportType.ServerSentEvents,
})
.withAutomaticReconnect()
.configureLogging(LogLevel.Information)
.build()
connection.on("ReceiveMessage", (json) => {
funcs.value.forEach(func => {
try {
func(JSON.parse(json))
} catch (error) {
console.error(error)
}
})
})
start()
async function start() {
try {
await connection.start()
} catch (err) {
console.error("Failed to connect with SSE", err)
setTimeout(start, 5000)
}
}
}
function onReceived(func) {
funcs.value.push(func)
}
return {
onReceived
}
})
如此一个最简单的SSE就完成了。