如何等待已建立的订阅?

11

我有以下的js代码:

stompClient.subscribe('/topic/clients', function (calResult) {
    updateClientsTable(JSON.parse(calResult.body));
});
$.get("/clients", null);

并且以下是服务器代码(最后一行调用它):

 @GetMapping(value = {"/clients"})
 @ResponseBody
 public void loadClients() {
      brokerMessagingTemplate.convertAndSend("/topic/clients", clientService.getClientList());
 }

有时前端会错过$.get("/clients", null);的结果。

据我所知,问题在于前端获取结果时订阅还没有完成。

如果将$.get("/clients", null);放在代码下面-所有内容都可以正常工作。

您能解释一下如何等待订阅建立吗?


我假设您已经通过.connect()建立了一个工作的STOMP连接,但是后续的订阅在查询主机之前无法接收到消息?STOMP不提供“成功”订阅的回调。 - DooMMasteR
它不会一直重现。我不理解短语:“直到你查询主机一次”。 - gstackoverflow
3个回答

1
我认为不将REST请求与此消息传递模式混合在一起会更有意义。
您是否考虑通过SockJS将“updateClients”命令发送到“/apps/updateClients”频道,该频道回复“/topic/clients”频道?

1
正如@light_303所提到的,将HTTP请求与通知机制混合使用并不好。您可以在客户端连接时注册(GET请求/clients),但是无法注册他何时断开连接。
您应该考虑以下其中一种方式。当用户订阅/topic/clients时:
  1. 您单独向他发送所有客户端列表的响应,然后仅推送更新。
  2. 您单独向他发送当前服务器时间或某种ID,然后仅推送更新。用户在GET请求/clients中使用给定的时间/ ID,并在那个时刻接收完整的客户端列表。在具有增量更新(即将新元素添加到列表)且其他情况不太好的情况下,此选项可能很好。
请参阅此问题:Sending message to specific user on Spring Websocket
这实在是荒谬,Spring 怎么会把事情复杂化呢。我建议你寻找其他框架来进行实时网络通信,比如 Vert.x 或 Netty 以及 Go 编程语言。使用 WebSockets 或 SockJS 替代 STOMP。所有这些技术都可以提供更灵活和高效的解决方案。另外,检查 Centrifugo 项目,也许与你的任务相关。

0
你可以使用来自 spring-messaging@SubscribeMapping 注解。
如果你已经按照 这里这里 的描述配置了 spring-messaging,那么服务端的代码可能如下所示:
@Controller
public class MessagingController {
    @SubscribeMapping("/clients")
    public List<Client> loadClients() {
        return clientService.getClientList();
    }
}

这样,您就不必调用$.get("/clients", null);,因为JS消息处理程序会在订阅发生后立即接收到loadClients()调用的结果。JS代码将如下所示:
stompClient.subscribe('/topic/clients', function (calResult) {
    updateClientsTable(JSON.parse(calResult.body));
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接