2016-10-02 112 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放在最上面作为传输。