2013-03-06 111 views
0

我使用Pubnub將實時消息從服務器發佈到客戶端(瀏覽器頁面)。使用Pubnub時,必須遵守其消息大小限制,有時會導致需要將消息分塊,發送數據,並在客戶端重新構建。根據Pubnub的建議,如果Pubnub.publish()函數調用速度過快(即消息片段僅通過for循環進行抽取),則可以確保傳遞每個消息塊。Ruby回調函數繼續執行另一個函數

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 

這導致徹底失敗 - 讓服務器完全鎖定到無限while循環,因爲(如果我不得不猜測)pubnub_do_send從未再次設置爲true。看看調試日誌,我看到第一條消息print(「Message 1 chunk 0 sent」),但從來沒有回調函數的輸出。 (可能是因爲它發現自己在無限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和塊步入回調仍然讓pubnub其信息附加到混合的方法嗎?這聽起來方式錯了,但也許用Ruby ...)

謝謝提前爲所有幫助。

回答

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 
+0

看起來像一個很好的解決方案,我會繼續前進,現在實行 - 謝謝! – MandM 2013-03-06 17:54:28

+0

其實,這看起來像一個模型方法,是否正確?我打算在控制器中實現,我想我仍然可以,只是想知道你的模型方法背後的想法是什麼。 – MandM 2013-03-06 17:56:52

+0

是的,模型是正確的地方。我不知道你的架構,所以這只是最簡潔的方法來演示 – quandrum 2013-03-06 18:02:15

相關問題