2016-10-02 110 views
0

如何在Rails 4中使用服務器發送事件並監聽多個callbakcs(創建和銷燬)?例如,Rails 4服務器發送事件

型號:

class Job < ActiveRecord::Base 
    after_create :notify_job_created 
    after_destroy :notify_job_destroyed 

    def self.on_create 
    Job.connection.execute "LISTEN create_jobs" 
    loop do 
     Job.connection.raw_connection.wait_for_notify do |event, pid, job| 
     yield job 
     end 
    end 
    ensure 
    Job.connection.execute "UNLISTEN create_jobs" 
    end 

    def self.on_destroy 
    Job.connection.execute "LISTEN destroy_jobs" 
    loop do 
     Job.connection.raw_connection.wait_for_notify do |event, pid, job| 
     yield job 
     end 
    end 
    ensure 
    Job.connection.execute "UNLISTEN destroy_jobs" 
    end 

    def notify_job_created 
    Job.connection.execute "NOTIFY create_jobs, '#{self.id}'" 
    end 

    def notify_job_destroyed 
    Job.connection.execute "NOTIFY destroy_jobs, '#{self.id}'" 
    end 
end 

控制器:

class StreamJobsController < ApplicationController 
    include ActionController::Live 

    def index_stream 
    response.headers['Content-Type'] = 'text/event-stream' 

    sse = SSE.new response.stream 
    begin 
     Job.on_create do |id| 
     job = Job.find(id) 
     stand = Stand.find(job.stand_id) 
     t = render_to_string(
      partial: 'projects/stand', 
      formats: [:html], 
      locals: {stand: stand} 
     ) 
     sse.write(t, event: 'create') 
     end 
     Job.on_destroy do |id| 
     job = Job.find(id) 
     sse.write(job.stand_id, event: 'destroy') 
     end 
    rescue IOError 
     # When the client disconnects, we'll get an IOError on write 
    ensure 
     sse.close 
    end 
    end 
end 

JS代碼:

$(function() { 
    var source = new EventSource('/jobs_stream'); 

    source.addEventListener('create', function(e){ 
    console.log('Create stand:', e.data); 
    $("table.project-stands.table.table-condensed").find("tbody#stand-list").prepend($.parseHTML(e.data)); 
    }); 

    source.addEventListener('destroy', function(e){ 
    console.log('Destroy stand: ', e.data); 
    var id = e.data; 
    $("table.project-stands.table.table-condensed").find("tr#stand_" + id).remove(); 
    }); 

source.addEventListener('finished', function(e){ 
    console.log('Close:', e.data); 
    source.close(); 
}); 
}); 

至於結果,我得到只聽create_jobs。我的控制器有什麼問題?謝謝

回答

0

我不認爲你的控制器有什麼問題。你的問題更多的是關於Postgres的通知。您是否對ActiveRecord模型中使用的方法進行了測試,以確保NOTIFY/LISTEN組合函數符合他們的要求?

至於結果,我得到只聽create_jobs

你是什麼意思?在您發佈的示例中,我沒有看到任何LISTEN內容進入SSE輸出。我真的建議你自己試驗一下模型,看看阻塞是否等着你使用隔離的函數,然後嘗試把SSE放在最上面作爲傳輸。