“现有订阅频道”,只订阅一次

时间:2013-07-24 12:04:06

标签: javascript pusher

我有一个小片段,抛出“现有订阅频道”异常,即使我只调用一次订阅方法。

这可以通过将“订阅”请求移到“state_change”处理程序之外来避免,但我想知道是什么原因造成这种情况?也许是Pusher库中的一个错误?

<!doctype html>
<html>
<body>
    <h1>Pusher subscribe testcase</h1>
    <p>Tip: check your console</p>
    <script src="https://d3dy5gmtp8yhk7.cloudfront.net/2.1/pusher.min.js"></script>
    <script>
        var pusher, channel;
        pusher = new Pusher('xxxxxxxxxxxxxxxxx');
        pusher.connection.bind('state_change', function(change){
            if(change.current === 'connected'){
                console.log('connected');
                channel = pusher.subscribe('test-channel');
                channel.bind('pusher:subscription_succeeded', function() {
                    console.log('subscribed');
                });
            }
        })
    </script>
</body>
</html>

这导致:

connected
subscribed
Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":null,"message":"Existing subscription to channel test-channel"}}}

2 个答案:

答案 0 :(得分:3)

虽然它看起来像是库中的错误(报告它!),但您无需绑定到state_change事件以订阅频道。

如果您在pusher.js中查看订阅事件的代码:

prototype.subscribe = function(channel_name) {
  var self = this;
  var channel = this.channels.add(channel_name, this);

  if (this.connection.state === 'connected') {
    channel.authorize(this.connection.socket_id, function(err, data) {
      if (err) {
        channel.handleEvent('pusher:subscription_error', data);
      } else {
        self.send_event('pusher:subscribe', {
          channel: channel_name,
          auth: data.auth,
          channel_data: data.channel_data
        });
      }
    });
  }
  return channel;
};

您会看到它会首先通过channels.add方法将您的频道添加到内部频道列表中,如下所示:

prototype.add = function(name, pusher) {
  if (!this.channels[name]) {
    this.channels[name] = createChannel(name, pusher);
  }
  return this.channels[name];
};

只会在您之前未订阅的情况下添加频道。

因此,如果您在建立连接之前订阅了频道,则Pusher客户端将仅将频道添加到列表中。客户端建立连接后,将通过subscribe方法为其列表中的每个频道再次调用subscribeAll方法:

this.connection.bind('connected', function() {
  self.subscribeAll();
});

此时this.connection.state connected,它会连接。

所以,重新绑定,不要费心绑定到state_change事件进行订阅,只需订阅,就像这样:

<!doctype html>
<html>
<body>
    <h1>Pusher subscribe testcase</h1>
    <p>Tip: check your console</p>
    <script src="https://d3dy5gmtp8yhk7.cloudfront.net/2.1/pusher.js"></script>
    <script>
        var pusher, channel;

        pusher = new Pusher('XXXXXXXXXXXXXXXX');
        channel = pusher.subscribe('test-channel');
        channel.bind('pusher:subscription_succeeded', function() {
            console.log('subscribed');
        });
    </script>
</body>
</html>

答案 1 :(得分:2)

它看起来像一个bug。如果在开发工具中打开“网络”选项卡并查看WebSocket连接“帧”信息,则可以看到发送两次的pusher:subscribe协议事件。但是,代码肯定只调用pusher.subscribe一次。

您应该通过Pusher支持或向github repo提交问题来提出此错误。

pusher:subscribe protocol event sent twice