Javascript 使用状态将数据从模型/数据库传递到通道

Javascript 使用状态将数据从模型/数据库传递到通道,javascript,elixir,phoenix-framework,phoenix-channels,Javascript,Elixir,Phoenix Framework,Phoenix Channels,我有一个简单的聊天应用程序,我建立,我想能够显示用户上传的图像(本地托管)旁边的用户名在频道的html页面。目前,我正在使用状态跟踪登录到频道等的用户。我能够覆盖fetch/2功能,因为它允许我使用用户模型数据向:metas符号添加几个映射字段 从大量的IO中我可以看出,检查每个函数的不同部分fetch/2,handle\u info/2,以及一些控制台。登录我的JS层,fetch/2函数实际上并没有从数据库中获取任何数据,也没有将其分配给:metas映射 这是我当前的fetch/2函数: de

我有一个简单的聊天应用程序,我建立,我想能够显示用户上传的图像(本地托管)旁边的用户名在频道的html页面。目前,我正在使用状态跟踪登录到频道等的用户。我能够覆盖
fetch/2
功能,因为它允许我使用用户模型数据向
:metas
符号添加几个映射字段

从大量的
IO中我可以看出,检查每个函数的不同部分
fetch/2
handle\u info/2
,以及一些控制台。登录我的JS层,
fetch/2
函数实际上并没有从数据库中获取任何数据,也没有将其分配给
:metas
映射

这是我当前的
fetch/2
函数:

def fetch(_topic, entries) do
  query =
    from u in User,
      where: u.id in ^Map.keys(entries),
      select: {u.id, u}

  users = query |> Repo.all |> Enum.into(%{})

  for {key, %{metas: metas}} <- entries, into: %{} do 
    {key, %{metas: metas, user: users[key]}}
end
我的用户[key]返回一个像这样的空映射,
%{}
并将输入转换为整数会抛出一个错误,
(Poison.EncodeError)无法对值进行编码:{nil,“users”}
如果我在elixir代码中转换它,
其中:u.id in^[“undefined”],选择:{u.id,u}(elixir)lib/enum.ex:1755:enum。“-reduce/3-lists^foldl/2-0-”/3-
如果我从JS层转换它

原始的
fetch/2
输出是一个数组,其
联机地址为:1492764577562
phx\u ref:
:metas
映射中的“OAyzaGE82xc=”
,以及
用户
变量中的我的用户id或电子邮件

我在这里遗漏了什么?我知道
fetch/2
函数只作为对
Presence.list/1
函数的回调执行,我在
handle\u info/2
channel函数中调用该函数。我还在JS层中调用
Presence.list
,并将其映射到我的Presence,以便生成列表在HTML中的用户名。我只是误解了这是如何工作的,还是有其他更简单的方法,我应该这样做?如果你需要看到更多的代码,我可以提供更多

编辑:我对这里发生的事情有了更好的理解。我的条目图实际上是这样的:

%{"1" => %{metas: [%{online_at: 1492798247818, phx_ref: "ELHwA+gWF+0="}]}} 
因此,基本上,用户id的字符串,
“1”
被映射到
元映射上
函数它无法从数据库中提取任何内容,因为它是一个字符串,但是,当我从JavaScript端将其更改为整数时,它会抛出一个错误,因为无论出于何种原因,phoenix都希望该键是字符串类型。奇怪的是,如果我将
id
id
更改为
电子邮件d尝试用电子邮件查询数据库,但它也不起作用。尽管数据库中的电子邮件是字符串,
metas
映射需要
条目的字符串键
映射


我将从头开始重建应用程序的此频道部分,并查看导致此问题的原因。然后我将返回并查看是否能够修复错误。

您应该首先验证条目映射中的密钥

ids = Map.keys(entries)
true = Enum.all?(ids, &is_integer/1)
当插入到查询中时,EXTO将字符串转换为整数:

iex(40)> Ecto.Query.from(u in Users, where: u.id in ^[1, 2, "3", nil], select: u.id) |> Repo.all()
输出以下调试日志:

[debug] QUERY OK source="users" db=0.8ms
SELECT u0."id" FROM "users" AS r0 WHERE (r0."id" = ANY($1)) [[1, 2, 3, nil]]
注意,它强制字符串“3”为整数,并允许nil

但是,地图将不会如此:

iex(42)> users = %{1 => %{name: "joe"}, 2 => %{name: "jill"}}
%{1 => %{name: "joe"}, 2 => %{name: "jill"}}
iex(43)> users["1"]
nil

因此,在使用
条目中的键进行数据库查找和地图查找的代码中,可能会产生不同的结果。

我已经发现问题与我的
fetch/2
函数本身没有多大关系,而是与我实现的状态模块和通道有关在本例中,基本上,
fetch/2
函数在每次有人进入聊天室时被调用4次,四次调用中有两次使用空列表值
[]

显然,您无法查询带有空列表的EXTO模型,因此在这种情况下它也会抛出错误。我尝试在fetch函数上设置防护以过滤空列表调用,但即使查询成功,它也不会向我显示我正在查找的
metas
映射数据

另外,另一个主要问题是我的
令牌的实现或缺乏实现。如果我使用令牌加入聊天室,而不仅仅是
用户
(也称为用户名),我就不必通过fetch function
metas
映射传递用户模型数据.实现后,我成功地将用户模型数据连接到频道,并通过JS层显示,最终将其放到客户端

无论如何,伙计们,谢谢你们的建议。你们可能还没有回答这个问题(这是我问错问题的过错),但你们确实帮助我达到了目的。同时,你们也给了我一些工具,让我能够更好地理解整个框架


如果/当我有任何问题时,我会确保在将问题发布到stack overflow之前我问的是正确的问题,这样我就不会浪费时间。

你能发布
IO的输出吗?在查询运行后检查
用户的
以及整个
获取
函数的返回值吗?你说它是c每次刷新页面时都会调用。您是否正在重新加载浏览器?如果是,这将删除您的频道并打开一个新频道,从而导致状态更新。我还发现,当某人的状态发生变化时,会发生很多状态更新。此外,请检查
中的键是否理解。您可能会收到一个字符串,一个nd您在用户中的id可能是一个整数(除非您在架构中使用二进制id)
{“1”=>%MyApp.User{uuuuuu meta\uuuuu:#exto.schema.Metadata,电子邮件:test@test.com,加密密码:“$pbkdf2-s”
iex(42)> users = %{1 => %{name: "joe"}, 2 => %{name: "jill"}}
%{1 => %{name: "joe"}, 2 => %{name: "jill"}}
iex(43)> users["1"]
nil