Rails 3.1 - JS - *.js.erb 中的 Socket.io-emit 未执行并阻止执行 jQuery-Function

Nor*_*Ben 5 javascript ruby-on-rails ruby-on-rails-3 socket.io ruby-on-rails-3.1

我想在我的 Rails-Project 中使用 node.js 来提供异步 io。我不想使用 juggernaut、faye 或类似的东西,因为我需要与 web-socket、服务器发送的事件和 spdy 的干净连接,而没有其他选择。我第一次尝试使用 node.js 现在是使用 Socket.io,只是为了使用 JavaScript 将数据提供给 node.js 模块。但它根本不起作用。

我的 application.js 看起来像这样:

// This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
//= require jquery
//= require jquery_ujs
//= require_tree .

window.socket = io.connect('http://localhost:8080/');
Run Code Online (Sandbox Code Playgroud)

在我的 application.html.erb 中正确加载了 io 的要求:

 <%= javascript_include_tag "application", "http://localhost:8080/socket.io/socket.io.js" %>
Run Code Online (Sandbox Code Playgroud)

现在我想使用套接字在 create.js.erb 中发出一个发送给所有监听客户端的事件:

$(function() {
  window.socket.emit('message', <%= @message =>);
};
$("#new_article")[0].reset();
Run Code Online (Sandbox Code Playgroud)

消息以这种方式在 ArticlesCrontroller 中创建:

def create
  @article = current_user.articles.build(params[:article])
  if @article.save
    msg = {:data => @article.to_json}
    @message = msg.to_json
  end
end
Run Code Online (Sandbox Code Playgroud)

我在另一个名为 index.js.erb 的视图中以这种方式侦听此事件:

$(function() {
  window.socket.on('message', function (msg) {
    $("#articles").prepend(<%= escape_javascript render(Article.new.from_json(msg.data)) %>);
  });
});
Run Code Online (Sandbox Code Playgroud)

Socket.io 看起来像这样:

var io = require('socket.io').listen(8080);

io.sockets.on('connection', function (socket) {
  socket.on('message', function () { });
  socket.on('disconnect', function () { });
});
Run Code Online (Sandbox Code Playgroud)

并且似乎工作正常,因为它告诉我它如何为请求的 js-File 提供服务:

info  - socket.io started
debug - served static /socket.io.js
Run Code Online (Sandbox Code Playgroud)

但它根本不起作用,尽管 create.js.erb 被渲染而没有错误:

Rendered articles/create.js.erb (0.5ms)
Completed 200 OK in 268ms (Views: 70.0ms | ActiveRecord: 14.6ms)
Run Code Online (Sandbox Code Playgroud)

即使用于重置表单的 jQuery-Function 也不会执行,如果没有尝试发出套接字事件,什么工作。文章被正确保存到数据库中,所以这不是问题。有人能告诉我问题可能出在哪里吗?

更新:我通过使用 chrome 的 JavaScript 调试器发现问题始于application.js中window.socket的定义。错误代码是:

Uncaught ReferenceError: io is not defined
  (anonymous function)
Run Code Online (Sandbox Code Playgroud)

但是io是在我在 application.html.erb 中加载的 socket.io.js-File 中定义的。我以这种方式为 application.js 做了一个解决方法:

$.getScript('http://localhost:8080/socket.io/socket.io.js', function(){
  window.socket = io.connect('http://localhost:8080/');
});
Run Code Online (Sandbox Code Playgroud)

现在的问题是:为什么我必须以这种方式获取脚本,尽管它是在 application.html.erb 中加载的?但是尽管有这种解决方法,但 create.js.erb 仍然不起作用。我会在睡了一会儿后尝试解决这个问题。

小智 1

我通常在相关清单中包含依赖项(在本例中为application.js)。

Rails 能够识别许多不同的资源路径,所有这些路径都会在编译之前进行检查。我倾向于将 (eg socket.io.js) 放入vendor/assets/javascripts并在清单中添加额外的行,如下所示:

//= require jquery
//= require jquery_ujs
//= require socket.io
//= require_tree .
Run Code Online (Sandbox Code Playgroud)