Ruby回调函数继续执行另一个函数

时间:2013-03-06 15:29:38

标签: ruby lambda callback pubnub

我正在使用Pubnub将实时消息从服务器发布到客户端(浏览器页面)。使用Pubnub时,必须遵守其消息大小限制,有时需要对消息进行分块,将其分段发送,并在客户端重建。根据Pubnub的建议,如果没有快速调用Pubnub.publish()函数(即如果消息片段只是通过for循环泵送),则可以确保传递消息的每个块。

Pubnub Ruby API在Pubnub.publish()中指定了3个必需参数,一个通道,一个消息和一个回调函数。下面显示的回调函数来自Pubnub的Ruby示例:

    @my_callback = lambda { |message| puts(message) }
    pn.publish(:channel => :hello_world,
      :message => "hi",
      :callback => @my_callback)

回调中的消息(不是发布中的“hi”消息)包含publish()调用的状态信息,其值为“已发送”和“消息为大” “,两者都会附有唯一的标识符。

所以在Pubnub引擎盖的某个地方,这个回调得到.call() - 我想知道是否有办法让我介入这个过程。更详细的说,我有一条需要分成三个块的消息,我想要发送块0,并且在回调中收到“已发送”状态后,我想发送块1,等...

我对lambda函数及其范围不太熟悉,这是我的第一次尝试:

    @my_callback = lambda { |message| 
                            puts(message) 
                            Rails.logger.debug("Setting pubnub_do_send to true from callback")
                            pubnub_do_send = true
                          }

    pubnub_do_send = true

    while !pubnub_message.nil?
      if pubnub_do_send 

        #Send pubnub message
        #Cut off first chunk of message (this is why I'm testing for nil)
        #Set pubnub_do_send to false

        Rails.logger.debug("Message #{message_id} chunk #{chunk_id} sent")
        pubnub_do_send = false
      end
    end

这导致完全失败 - 让服务器完全锁定在无限循环中,因为(如果我不得不猜)pubnub_do_send再也没有设置为true。查看调试日志,我看到第一条消息打印(“消息1块0发送”),但从未看到回调函数的输出。 (可能是因为它发现了无限的while循环)

必须有一个干净的方法来做到这一点,我可以在某种程度上重构代码,分块消息并先存储到数组中,然后简单地循环遍历数组发送,但我觉得解决方案离我很远,我对lambda函数和回调都不太方便。

我觉得解决方案应该是这样的:

    @my_callback = lambda { |message| 
                            puts(message) 
                            send_pubnub_message(message_id, chunk_id, chunk)
                          }

    def send_pubnub_message(message_id, chunk_id, chunk)
      #Send pubnub message
      #Send message_id, next chunk_id, and next chunk to my_callback
    end

但问题是当my_callback获得某些关于消息的状态而不是我直接调用它时,Pubnub会调用Pubnub.publish()! (有没有办法让我将message_id,chunk_id和chunk插入回调,而仍然让pubnub将其消息附加到混合中?这听起来有点不对,但也许是Ruby ...)< / p>

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您不应该尝试在回调中处理消息块状态。它只有一个责任,通知发布的状态。但是,您可以在邮件中插入内容。我可能会创建一个知道它当前状态的消息包装器,并在lambda中发送它,因此您不必跟踪它。我没有测试过以下代码,但这里是我正在谈论的一个例子:

class Message
  attr_accessor :id, :message, :chunked_message, :chunk_id
  def initialize(id, message)
    @id, @message = id, message
    chunk_message
  end
  def current_chunk
    @chunked_message[@chunk_id]
  end
  def next_chunk
    @chunk_id += 1
    self
  end
  def more?
    @chunked_message.length > chunk_id
  end
  private
  def chunk_message 
    implement splitting message here
  end
end 


def send_pubnub_message(message)
  pn.publish(:channel => :hello_world,
  :message => message.current_chunk
  :callback => lambda { |status| 
                        puts(status)
                        case status[0] // 1 = success, 0 = fail
                        when 1
                          send_pubnub_message(message.next_chunk) if message.more?
                        when 0
                          handle_pubnub_error(status[1], message)
                        end
                      }
end