我是使用Signalr的初学者,正在查看一些例子。
是否可以从服务器向客户端发送消息并等待从中返回?或者是否可以保证在答案之后会使用相同的会话?
我的问题是因为在给定的流程中,在一个事务中,我需要询问用户是否要继续进行更改。我以前无法提出这个问题,因为验证应该在已进行更改的同一会话中完成(但尚未确认)。
答案 0 :(得分:6)
重申Jaime Yule的评论,WebSockets是双向通信,不遵循请求/响应架构进行消息传递。鉴于围绕WebSockets的通信非常流畅,这些要点对于您当前(和未来)的场景都要记住:
答案 1 :(得分:1)
在Invoke中使用以下形式等待并直接返回响应(就像“真正的”同步方法调用一样)
var persons = hubProxy.Invoke<IEnumerable<Person>>("GetPersonsSynchronous", SearchCriteria, noteFields).Result;
foreach (Person person in persons)
{
Console.WriteLine($"{person.LastName}, {person.FirstName}");
}
答案 2 :(得分:1)
有可能,但我不建议(依靠)它。
而且这不是一个很好的解决方案(使用静态事件,并且对于如此简单的事情非常复杂)。
故事是这样的:
确保客户端和服务器知道connectionId
-他们可能已经知道了,但是我想不出一种方法来访问它。
等待NotificationService.ConfirmAsync
...将在客户端上调用confirm
...将等待用户提供的答案
...并使用集线器中的Callback
将其发送回服务器。
...,它将通过静态事件从NotificationService
通知回调
...会将message
切换回ConfirmAsync
(使用AutoResetEvent
)
...希望仍在等待中:)
客户端和服务器都设置了10秒的超时时间。
中心:
// Setup as /notification-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);
}
}
服务:
// Wire it up using DI
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;
// using Noty v3 (https://ned.im/noty/)
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;
// Picked up by a form and posted to the server
document.querySelector(".connection-id-input").value = connectionId;
});
});
对我来说,这是将其放入我正在研究的项目中的复杂方法。
看起来好像真的会回来,以后再咬你...