我有一個簡單的聊天應用程序,我希望能夠在頻道的html頁面上的用戶名旁邊顯示用戶上傳的圖像(本地託管)。目前,我使用狀態來跟蹤登錄到頻道的用戶等。我可以覆蓋fetch/2
函數,理解它允許我使用用戶模型數據將一對地圖字段添加到:metas
符號。使用存在將數據從模型/數據庫傳遞到頻道
從我可以根據廣泛的IO.inspecting
知道每個函數的不同部分; fetch/2
,handle_info/2
和一些console.logging在我的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
它基本上是直接從文檔撕開。理論上,上面的函數應該查詢我的用戶模型,並根據通過條目映射傳遞給它的User.id
獲取所有用戶數據。 Users[keys]
返回爲空,儘管users
是我的用戶模型的完整映射。
此外,根據文檔,查詢只能在連接上運行,以免超載數據庫,但它似乎每次刷新頁面時運行4-5次。另外要注意的是,user.id
裏面的條目似乎是一個字符串類型。林不知道這是否重要,我試過從JS層傳遞一個整數,也使用Interger.parse
從實際的fetch/2
函數來改變這個無濟於事。
當我檢查用戶映射我得到這個:
{"1" => %MyApp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "[email protected]", encrypt_pass: "$pbkdf2-
sha512$160000$ebfY956TgIXhEAF.mqLJAg$QWzBubfeiy4Xrf.EsFiU0jEZAuKvV4ZO5a
8QpeFr817C61DuaNfyo56WWzj6jak2homCFWAINbPrFtCSXUPWTw", gravatar: %
{file_name: "logo.png", updated_at: #Ecto.DateTime<2017-04-20 22:00:08>},
id: 1, inserted_at: ~N[2017-04-20 22:00:09.071000], password: nil,
updated_at: ~N[2017-04-20 22:00:09.090000]}}
我的用戶[關鍵]返回一個空的地圖這樣%{}
,如果我內將其轉換的輸入轉換成整數拋出一個錯誤,(Poison.EncodeError) unable to encode value: {nil, "users"}
如果我將它從JS層轉換成。
原來fetch/2
輸出爲online_at: 1492764577562
和phx_ref: "OAyzaGE82xc="
在:metas
地圖在users
VAR的數組和我的用戶ID或電子郵件。
這是什麼,我在這裏失蹤?我知道fetch/2
函數只是作爲回調函數,我在調用handle_info/2
通道函數中調用Presence.list/1
函數。我還在我的JS層中調用Presence.list
,並將其映射到我的存在,以便我可以在HTML中生成用戶名列表。我只是誤解了這是如何工作的,還是有其他更簡單的方法,我應該繼續這樣做?如果您需要查看更多代碼,我可以提供更多代碼。
編輯:我對這裏發生的事情有了更好的理解。我的實體的映射表實際上是這樣的:
%{"1" => %{metas: [%{online_at: 1492798247818, phx_ref: "ELHwA+gWF+0="}]}}
所以基本上,用戶ID字符串,"1"
被映射到metas
地圖。當我試圖用Map.keys(entries)
函數將該鍵從地圖中取出時,它不能從數據庫中取出任何東西,因爲它是一個字符串,但是,當我將它從JavaScript端更改爲整數時,它將引發錯誤,因爲無論出於什麼原因鳳凰期待該鍵是一個字符串類型。奇怪的是,如果我將id
從id
更改爲email
並嘗試使用電子郵件查詢數據庫,它也不起作用。儘管數據庫中的電子郵件地址是字符串,並且metas
地圖期望地圖的entries
字符串鍵。
我打算從頭開始重建應用程序的這個頻道部分,看看是什麼導致了這個問題。然後我會回來看看我是否能夠解決這個錯誤。
你可以發佈'IO的輸出。在查詢運行後檢查'users'和這個'fetch'函數的返回值? – Dogbert
你說每次刷新頁面時都會調用它。你正在瀏覽器重新加載?如果是這樣,那麼這會拋棄你的頻道並打開一個新頻道,導致在線更新。我還發現,當有人出現變化時,會有很多狀態更新發生。另外,檢查你的'for'理解的關鍵。你可能會得到一個字符串,並且你的用戶id可能是一個整數(除非你在schema中使用二進制ID) –
'{「1」=>%MyApp.User {__ meta__:#Ecto.Schema.Metadata < :加載, 「用戶」>, 電子郵件: 「[email protected]」, encrypt_pass: 「$ PBKDF2-SHA512 $ 160000 $ ebfY956TgIXhEAF.mqLJAg $ QWzBubfeiy4Xrf.EsFiU0jEZAuKvV4ZO5a8QpeFr817C61DuaNfyo56WWzj6jak2homCFWAINbPrFtCSXUPWTw」, 的gravatar:%{FILE_NAME:爲 「logo.png」 , updated_at:#Ecto.DateTime <2017-04-20 22:00:08>},id:1, inserted_at:〜N [2017-04-20 22:00:00 09.071000],密碼:無, updated_at :〜N [2017-04-20 22:00:00 09.090000]}}'這是用戶檢查,這裏是用戶[鍵]檢查。 '%{}' – Abeltensor