这是可能的,但我不建议(依赖)这样做。而且这不是一个好看的解决方案(使用静态事件并且对于这么简单的事情而言相当复杂)。
故事背景如下:
确保客户端和服务器知道连接ID - 他们可能已经知道了,但我无法找到一种访问它的方法。
等待NotificationService.ConfirmAsync,
... 这将调用客户端上的 confirm,
... 等待用户提供的答案,
... 并使用Hub的Callback将其发送回服务器。
... 这将通过静态事件通知NotificationService的回调函数,
... 这将把消息交还给ConfirmAsync(使用AutoResetEvent)。
... 希望此时仍在等待:)
客户端和服务器都设置了10秒的超时时间。
Hub:
public class NotificationHub : Hub {
public string ConnectionId() => Context.ConnectionId;
public static event Action<string, string> Response;
public void Callback(string connectionId, string message) {
Response?.Invoke(connectionId, message);
}
}
服务:
public class NotificationService {
private readonly IHubContext<NotificationHub> _notificationHubContext;
public NotificationService(IHubContext<NotificationHub> notificationHubContext) {
_notificationHubContext = notificationHubContext;
}
public async Task<string> ConfirmAsync(string connectionId, string text, IEnumerable<string> choices) {
await _notificationHubContext.Clients.Client(connectionId)
.SendAsync("confirm", text, choices);
var are = new AutoResetEvent(false);
string response = null;
void Callback(string connId, string message) {
if (connectionId == connId) {
response = message;
are.Set();
}
}
NotificationHub.Response += Callback;
are.WaitOne(TimeSpan.FromSeconds(10));
NotificationHub.Response -= Callback;
return response;
}
}
客户端js:
var conn = new signalR.HubConnectionBuilder().withUrl("/notification-hub").build();
var connId;
function confirm(text, choices) {
return new Promise(function (resolve, reject) {
var n = new Noty({
text: text,
timeout: 10000,
buttons: choices.map(function (b) {
return Noty.button(b, 'btn', function () {
resolve(b);
n.close();
});
})
});
n.show();
});
}
conn.on('confirm', function(text, choices) {
confirm(text, choices).then(function(choice) {
conn.invoke("Callback", connId, choice);
});
});
conn.start().then(function() {
conn.invoke("ConnectionId").then(function (connectionId) {
connId = connectionId;
document.querySelector(".connection-id-input").value = connectionId;
});
});
对我来说,这太复杂了,无法将其纳入我正在开发的项目中。
它看起来真的像是以后会反噬你的东西...