React 客户端无法正确分发接收到的 ActionCable 广播
React client has trouble properly distributing received ActionCable broadcast
在这两种浏览器上,我的聊天应用程序都按预期运行 2-3 轮消息。之后,我在 Safari 上多次出现相同的消息,但在 Chrome 我的问题是消息完全停止。
更新:
自从最初发布我的问题后,我尝试以相反的顺序登录 Safari 和 Chrome。当我这样做时,问题实际上发生了变化。在控制台中,我看到无论哪个浏览器第二个登录到聊天室,都会收到 2 个或更多广播实例,而第一个登录的用户将不会收到任何消息。
我最初在接收广播时遇到了问题,但通过使用 npm 包 react-actioncable-provider 解决了这个问题。我的问题和答案可以在这里找到:
我已经将 cable.yml 适配器设置为 redis、postgresql 和异步进行了测试。正如预期的那样,异步根本不起作用。无论我使用 redis 还是 postgresql 作为我的适配器,都会发生同样的问题。
我正在 MacBook Air 上开发和测试。我的ruby版本是2.6.2,我的rails版本是5.2.2.
这是我的 messages_channel.rb:
class MessagesChannel < ApplicationCable::Channel
def subscribed
@game = Game.find(params[:game_id])
stream_for @game
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
这是我的 messages_controller.rb:
中的创建函数
def create
@game = Game.find(message_params[:game_id])
@message = Message.new(message_params)
if @message.save
serialized_data = ActiveModelSerializers::Adapter::Json.new(
MessageSerializer.new(@message)
).serializable_hash
puts "serialized_data"
MessagesChannel.broadcast_to @game, serialized_data
end
end
这是我使用 redux 编写的客户端代码:
import { ActionCable } from 'react-actioncable-provider';
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
class Cable extends Component {
render () {
return (
<Fragment>
<ActionCable
key={this.props.game_id}
channel={{ channel: "MessagesChannel", game_id: this.props.game_id }}
onReceived={(data) => {
console.log("MessagesChannel recvd data: ",data)
this.props.getMessages(data.message)
}}
/>
</Fragment>
)
}
}
const mapStateToProps = state => {
return { state }
}
const mapDispatchToProps = dispatch => {
return {
getMessages: data => dispatch({ type: "UP_MSG", payload: data })
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Cable);
当我的客户端成功接收到来自 actioncable 的广播数据时,我的 reducer 被调用 action.type "UP_MSG"。在那个开关盒内,我有一个 console.log 并且可以在 Chrome 和 Safari 中看到,不仅没有显示消息,而且在一段时间后没有收到消息的时间。在接收多条消息的浏览器上,我可以看到我的 "UP_MSG" 案例中的 console.log 在我的 reducer 中出现的次数与消息出现的次数一样多。
我没有看到终端的后端输出有任何不同。因为该行为是相同的,并且因为两个浏览器都有不同的错误,所以我认为问题一定出在客户端上。
即使您没有答案,任何有关调试的有用想法也将不胜感激。感谢您阅读到这里!
虽然起初我相当确定这是一个前端问题,但事实证明我错了。当我离开我的笔记本电脑一分钟时,我首先意识到这可能是一个性能问题,并发现所有消息确实都传输到 "silent" 浏览器 window,只是发生得很慢.
搜索我的后端代码,我找不到任何特别会降低性能的东西。特别是当我在一个只有一个群聊室的演示分支中工作时,不需要整理属于哪里。
搜索时,我找到了这篇文章:https://evilmartians.com/chronicles/anycable-actioncable-on-steroids
这让我找到了 github 上的 anycable-rails 的文档:https://github.com/anycable/anycable-rails
在我的 MacBook Air 上通过 brew 安装 anycable-go,然后按照 anycable-rails 文档中提供的步骤将 gem 添加到我的 rails 后端对我有用.
一旦我配置并安装了 anycable-rails,我的应用程序就不再有问题了。
在这两种浏览器上,我的聊天应用程序都按预期运行 2-3 轮消息。之后,我在 Safari 上多次出现相同的消息,但在 Chrome 我的问题是消息完全停止。
更新:
自从最初发布我的问题后,我尝试以相反的顺序登录 Safari 和 Chrome。当我这样做时,问题实际上发生了变化。在控制台中,我看到无论哪个浏览器第二个登录到聊天室,都会收到 2 个或更多广播实例,而第一个登录的用户将不会收到任何消息。
我最初在接收广播时遇到了问题,但通过使用 npm 包 react-actioncable-provider 解决了这个问题。我的问题和答案可以在这里找到:
我已经将 cable.yml 适配器设置为 redis、postgresql 和异步进行了测试。正如预期的那样,异步根本不起作用。无论我使用 redis 还是 postgresql 作为我的适配器,都会发生同样的问题。
我正在 MacBook Air 上开发和测试。我的ruby版本是2.6.2,我的rails版本是5.2.2.
这是我的 messages_channel.rb:
class MessagesChannel < ApplicationCable::Channel
def subscribed
@game = Game.find(params[:game_id])
stream_for @game
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
这是我的 messages_controller.rb:
中的创建函数 def create
@game = Game.find(message_params[:game_id])
@message = Message.new(message_params)
if @message.save
serialized_data = ActiveModelSerializers::Adapter::Json.new(
MessageSerializer.new(@message)
).serializable_hash
puts "serialized_data"
MessagesChannel.broadcast_to @game, serialized_data
end
end
这是我使用 redux 编写的客户端代码:
import { ActionCable } from 'react-actioncable-provider';
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
class Cable extends Component {
render () {
return (
<Fragment>
<ActionCable
key={this.props.game_id}
channel={{ channel: "MessagesChannel", game_id: this.props.game_id }}
onReceived={(data) => {
console.log("MessagesChannel recvd data: ",data)
this.props.getMessages(data.message)
}}
/>
</Fragment>
)
}
}
const mapStateToProps = state => {
return { state }
}
const mapDispatchToProps = dispatch => {
return {
getMessages: data => dispatch({ type: "UP_MSG", payload: data })
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Cable);
当我的客户端成功接收到来自 actioncable 的广播数据时,我的 reducer 被调用 action.type "UP_MSG"。在那个开关盒内,我有一个 console.log 并且可以在 Chrome 和 Safari 中看到,不仅没有显示消息,而且在一段时间后没有收到消息的时间。在接收多条消息的浏览器上,我可以看到我的 "UP_MSG" 案例中的 console.log 在我的 reducer 中出现的次数与消息出现的次数一样多。
我没有看到终端的后端输出有任何不同。因为该行为是相同的,并且因为两个浏览器都有不同的错误,所以我认为问题一定出在客户端上。
即使您没有答案,任何有关调试的有用想法也将不胜感激。感谢您阅读到这里!
虽然起初我相当确定这是一个前端问题,但事实证明我错了。当我离开我的笔记本电脑一分钟时,我首先意识到这可能是一个性能问题,并发现所有消息确实都传输到 "silent" 浏览器 window,只是发生得很慢.
搜索我的后端代码,我找不到任何特别会降低性能的东西。特别是当我在一个只有一个群聊室的演示分支中工作时,不需要整理属于哪里。
搜索时,我找到了这篇文章:https://evilmartians.com/chronicles/anycable-actioncable-on-steroids
这让我找到了 github 上的 anycable-rails 的文档:https://github.com/anycable/anycable-rails
在我的 MacBook Air 上通过 brew 安装 anycable-go,然后按照 anycable-rails 文档中提供的步骤将 gem 添加到我的 rails 后端对我有用.
一旦我配置并安装了 anycable-rails,我的应用程序就不再有问题了。