【问题标题】:How to handle broadcasting a dynamic list to javascript clients in cometd如何处理在 cometd 中向 javascript 客户端广播动态列表
【发布时间】:2016-01-13 09:57:17
【问题描述】:

我的网络服务器上有一个动态列表。我希望我的 Javascript 客户端能够订阅一个频道,该频道将在添加项目并从服务器上的列表中删除时进行广播。问题在于当客户端订阅频道时如何传达列表。理想情况下,客户端以服务器上的项目列表结束,然后开始处理添加和删除。

鉴于我对 Cometd 的理解,我看不到一种方法可以触发来自服务器的消息,该消息在订阅时发送列表的内容。如果我不能这样做,那么我必须求助于对服务器的调用来发送列表的非cometd 服务。该解决方案给我留下了可能会错过添加或删除的情况。

在我看来,这似乎是一个更普遍的问题,但不是我在其他地方看到的解决方案。

任何意见表示赞赏。

【问题讨论】:

    标签: javascript angularjs client-server cometd


    【解决方案1】:

    CometD 中,您可以使用两种方法将列表广播给客户端:

    • 每次更改时发送整个列表
    • 在客户端首次连接时发送整个列表,然后只发送更改

    第一种方法适用于小列表,第二种方法适用于较大的列表。

    我将讨论第二种方法,因为所使用的技术也适用于第一种方法。

    作为使代码 sn-ps 更清晰的示例,假设您要通过频道 /room1/members 发送聊天室成员列表。

    在订阅时发送整个列表

    在您的房间配置代码中,您向会员频道注册了SubscriptionListener

    private void configureRoom(String roomName) {
        final String channelName = "/" + roomName + "/members";
        ServerChannel channel = bayeuxServer.createChannelIfAbsent(channelName).getReference();
        channel.addListener(new SubscriptionListener() {
            @Override
            public void subscribed(ServerSession session, ServerChannel channel, ServerMessage message) {
                // Send back the whole list to the subscriber.
                session.deliver(sender, channelName, memberList);
            }
        });
    

    请注意,您想在这里使用ServerSession.deliver() 将整个列表发送给该订阅者:其他订阅者已经拥有该列表,因此无需将其广播给所有订阅者。

    发送列表更改

    当列表发生变化时,您可以只广播变化,例如当成员离开聊天室时:

    private void memberLeft(String roomName, String memberName) { 
        int index = memberList.indexOf(memberName);
        if (index < 0) {
            return;
        }
        memberList.remove(index);
        Map<String, Object> data = new HashMap<>();
        data.put("action", "remove");
        data.put("index", index);
        String channelName = "/" + roomName + "/members";
        ServerChannel channel = bayeuxServer.getChannel(channelName);
        channel.publish(sender, data);
    }
    

    请注意,您要在此处使用ServerChannel.publish() 将更改广播给所有订阅者。

    客户端将看到两种类型的消息到达通道/room1/members:一种是数据是字符串列表 - 然后它会知道它是整个列表,另一种是数据是对象 - 然后它会知道这是一个列表更改。

    对于后者,数据将有一个action 字段告诉您需要执行什么操作,还有一个index 字段告诉您需要在哪个索引处操作。 这两条消息的格式完全取决于您。

    应对网络中断

    当客户端暂时离线时,服务器可能会发送列表更改。对于这种情况,CometD 提供了message acknowledgement extension,它提供了服务器到客户端保证的消息传递。

    对于较长的离线时间,客户端将与服务器重新握手,因此它将在重新订阅时获得完整列表。 请遵循this sectionCometD documentation 中描述的指南。

    【讨论】:

    • 谢谢西蒙,这正是我想要的。不过,虽然我有你的耳朵,但你知道任何 Angularjs cometD 服务吗? gist.github.com/simon-jouet/4543421 有这个,但是 'addListener' 和 'subscribe' 的签名看起来不对。
    • CometD 3.1.x 支持 Angular。您现在可以使用快照,一旦我完成了针对 3.1.x 的其他几个问题,就会发布一个版本。请标记为已回答:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 2019-04-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多