如何在凤凰框架聊天应用程序中向不同用户发送消息

时间:2017-07-25 10:16:42

标签: elixir phoenix-framework elixir-framework phoenix-channels

我正在使用phoenix框架创建不同类型的聊天应用。就我而言,我们有聊天室但不能正常聊天室。

每个用户都有自己的房间,他可以使用不同的设备(手机,电脑,其他一些来源)加入他的房间。

用户A有自己的房间,用户B有自己的房间,这两个成员不像现实世界中的正常情况那样连接到单个房间。

现在我的用户A想要向用户B发送消息

消息数据,例如:

from : A  
to :B  
message : test message   

这是app.js的片段我曾经连接到用户的特定房间:

let room = socket.channel("room:"+  user, {})
room.on("presence_state", state => {
  presences = Presence.syncState(presences, status)
  console.log(presences)
  render(presences)
})

这是连接房间功能的后端片段
/web/channel/RoomChannel.ex

  def join("room:" <> _user, _, socket) do
    send self(), :after_join
    {:ok, socket}
  end

但现在我陷入困境,因为我找不到在用户之间发送消息的方法。 例如:无法确定使用此特定方案向用户B发送用户A消息的方式

这是此聊天应用的基本架构师:

enter image description here

这是Roomchannel文件中的其余代码

def handle_info(:after_join, socket) do
    Presence.track(socket, socket.assigns.user, %{
      online_at: :os.system_time(:millisecond)

    })
    push socket, "presence_state", Presence.list(socket)
    {:noreply, socket}
  end

  def handle_in("message:new", message, socket) do
    broadcast! socket, "message:new", %{
      user: socket.assigns.user,
      body: message,
      timestamp: :os.system_time(:millisecond)
    }
    milisecondstime = :os.system_time(:millisecond)
    [room, user] = String.split(Map.get(socket, :topic), ":")
    data = Poison.encode!(%{"created_at" => :os.system_time(:millisecond), "updated_at" => :os.system_time(:millisecond), "uuid" => UUID.uuid1(), "date" => :os.system_time(:millisecond), "from" => user, "to" => user, "message" => message})
    Redix.command(:redix, ["SET", UUID.uuid1(), data]) 
    {:noreply, socket}
  end

有人能告诉我一些可以在用户聊天室之间传递消息的方式吗?

我使用redis存储数据和 this是我关注的基本聊天应用程序,感谢开发人员。

1 个答案:

答案 0 :(得分:1)

查看Phoenix.Endpoint.broadcast 您可以使用broadcast/3函数

将消息发送到给定主题

您可以采用的另一种方法是在用户加入频道join功能

时为每个用户订阅一个唯一的私人主题
def join("room:" <> _user, _, socket) do
    send self(), :after_join
    MyApp.Endpoint.subscribe("private-room:" <> user) # subscribe the connecting client to their private room
    {:ok, socket}
end

然后在handle_in("message:new",message, socket)中从消息有效负载中提取接收用户ID并调用

Endpoint.broadcast

def handle_in("message:new", message, socket) do

    MyApp.Endpoint.broadcast!("private-room:" <> to_user , "message:new",%{
        user: socket.assigns.user,
        body: message,
        timestamp: :os.system_time(:millisecond)
   }) #sends the message to all connected clients for the to_user

    {:noreply, socket}
end