我的app / assets / javascripts / channels文件夹中有一个messages.js.erb文件,该文件应生成代码以从数据库中获取每个聊天室并为该聊天室创建频道订阅。
这是我的messages.js.erb文件
//**app/assets/javascripts/channels/messages.js.erb**
$(document).on('turbolinks:load', function() {
submitNewMessage();
});
<% Chatroom.all.each do |chatroom| %>
App['room' + <%=chatroom.id%>] = App.cable.subscriptions.create({channel: 'MessagesChannel', room: <%=chatroom.id%>}, {
received: function(data) {
$("[data-chatroom='" + this.chatroomId + "']").removeClass('hidden');
return $("[data-chatroom='" + this.chatroomId + "']").append(data.message);
},
setChatroomId: function(chatroomId) {
this.chatroomId = chatroomId;
}
});
<% end %>
function submitNewMessage(){
//console.log(uid);
$('textarea#message_content').keydown(function(event) {
if (event.keyCode === 13) {
var msg = event.target.value;
var chatroomId = $("[data-chatroom]").data().chatroom;
var uid = $('#uid').val();
//console.log(uid);
App['room' + chatroomId].setChatroomId(chatroomId);
App['room' + chatroomId].send({message: msg, chatroom_id: chatroomId, user_id: uid});
$('[data-textarea="message"]').val(" ");
return false;
}
});
}
最好每次创建一个新聊天室时重新加载此文件,但rails在首次加载后缓存(precompiling?
)文件(asset?
)并在每次请求时提供它。
所以,问题是:每次创建一个新的聊天室时,如果我想让它流式传输(即能够发送消息立即流式传输给该聊天室的每个参与者),我需要手动更改文件(通过添加空格,或添加注释或记录到控制台,something
)并保存它以便rails认为文件已更改并重新加载它,从而再次迭代所有Chatroom
s包含新创建的聊天室。
否则,当我在尚未流媒体的聊天室中发布消息(点击输入)时(因为缓存版本无法看到它)我得到了
未捕获的TypeError:无法读取未定义的属性“setChatroomId” 在HTMLTextAreaElement。 (messages.self-cbf13df66ead12b7956faa24e880ce07c0289634216a096fafd4ac1c6d262f43.js体= 1:436) 在HTMLTextAreaElement.dispatch(jquery-1.11.3.min.self-ad66c584c2469d2bb527ba7aef5893549f1554ccc8ab3ccb43bd09ce8c3bf7a1.js?body = 1:5) 在HTMLTextAreaElement.r.handle(jquery-1.11.3.min.self-ad66c584c2469d2bb527ba7aef5893549f1554ccc8ab3ccb43bd09ce8c3bf7a1.js?body = 1:5)
在我的浏览器控制台(开发人员工具)中。错误的来源是:
以下是生成的messages.js代码(为简洁起见,重复修剪线条)
$(document).on('turbolinks:load', function() {
submitNewMessage();
});
App['room' + 1] = App.cable.subscriptions.create({channel: 'MessagesChannel', room: 1}, {
received: function(data) {
$("[data-chatroom='" + this.chatroomId + "']").removeClass('hidden');
return $("[data-chatroom='" + this.chatroomId + "']").append(data.message);
},
setChatroomId: function(chatroomId) {
this.chatroomId = chatroomId;
}
});
.
.
.
.
.
.
.
App['room' + 37] = App.cable.subscriptions.create({channel: 'MessagesChannel', room: 37}, {
received: function(data) {
$("[data-chatroom='" + this.chatroomId + "']").removeClass('hidden');
return $("[data-chatroom='" + this.chatroomId + "']").append(data.message);
},
setChatroomId: function(chatroomId) {
this.chatroomId = chatroomId;
}
});
function submitNewMessage(){
//console.log(uid);
$('textarea#message_content').keydown(function(event) {
if (event.keyCode === 13) {
var msg = event.target.value;
var chatroomId = $("[data-chatroom]").data().chatroom;
var uid = $('#uid').val();
App['room' + chatroomId].setChatroomId(chatroomId); // <-- line 436
App['room' + chatroomId].send({message: msg, chatroom_id: chatroomId, user_id: uid});
$('[data-textarea="message"]').val(" ");
return false;
}
});
}
我理解这个错误是显而易见的,因为{id}尚未为我们尝试发布消息的id 38的新聊天室定义App['room' + 38]
(此处,所有聊天室的ID都是&gt; 37)
但是,如何让rails了解每次创建新聊天室时都需要重新加载此文件。如果不是每次,那么每次请求?基本上,告诉rails不要预编译/缓存它,以便我可以在移动中创建聊天室并从中流式传输?
答案 0 :(得分:1)
将messages.js.erb
文件移至lib/assets
或vendor/assets
目录。
来自doc:
...可以使用lib / assets或vendor / assets下的资产 通过申请表明包含但不再是申请表的一部分 预编译数组。
确保它没有列在application.js
中,你应该好好去。
答案 1 :(得分:1)
我猜您使用了https://www.thegreatcodeadventure.com/rails-5-action-cable-with-multiple-chatroom-subscriptions/中的教程,这是一个很好的教程。 您不应该通过更改预编译来解决此问题。而是更有效地订阅渠道。
例如,从外部执行该方法。使用助手方法仅获取所需的房间。
var adal = require("adal-node");
const TENANT = "{tenant-name-here}.onmicrosoft.com";
const CLIENT_ID = "{Application-id-here}";
const CLIENT_SECRET = "{Application-key-here}";
function getToken() {
return new Promise((resolve, reject) => {
const authContext = new adal.AuthenticationContext(
`https://login.microsoftonline.com/${TENANT}`
);
authContext.acquireTokenWithClientCredentials(
GRAPH_URL,
CLIENT_ID,
CLIENT_SECRET,
(err, tokenRes) => {
if (err) {
reject(err);
}
resolve(tokenRes.accessToken);
}
);
});
}
在订阅方法中,检查您是否尚未订阅。
subscripeToChannels(<%= raw chatrooms_for_client %>)
如果创建了一个新房间,则可以在create.js.erb文件中再次执行subscripeToChannels。
for (var i = 0; i < App.cable.subscriptions.subscriptions.length; i++) {
var s = App.cable.subscriptions.subscriptions[i]
var JSONObject = JSON.parse(s.identifier);
var room = JSONObject["room"];
if (room == chatroomId)
{
preventMultipleSubscripe = true;
}
}
对我来说,这可以更简洁地解决