2013-11-28 98 views
3

在模板下面這個簡單的功能通常會在我的失敗,因爲user對象是不確定的,即使我登錄:在車把模板函數未定義流星用戶對象

Template.hello.userData = function() { 
    var user = Meteor.users.findOne(Meteor.userId()); 
    return user.emails[0].address; 
}; 

這很容易複製:

  • 上的命令行:
    • 流星創建測試用戶
    • CD試驗用戶
    • 流星添加帳戶密碼
    • 流星添加帳戶的UI
  • 編輯測試user.js的並添加「用戶數據」代碼(以上)到isClient塊
  • 編輯測試用戶。 html和裏面添加「你好」的模板:{{loginButtons}} {{用戶數據}}
  • 轉到應用程序並創建一個帳戶,其招牌你,你會得到在控制檯中的錯誤: Uncaught TypeError: Cannot read property 'emails' of undefined

這個陰險的東西是「通常」的一部分:它有時會成功,因此可能會涉及競爭條件......並且它可能與加載依賴項的順序有關。

我實際上是在一個更復雜的應用程序中試圖訪問我登錄用戶的'profile'屬性(它存在,我保證)。它在不同的瀏覽器中給出稍微不同的錯誤消息;這裏是Chrome的堆棧跟蹤:

 
Exception from Deps recompute: TypeError: Cannot read property 'profile' of undefined 
    at Object.Template.workbook.owner (http://localhost:3000/client/client.js?153b3db62478692678dd9fdf9f1a9dd0b6b6a76e:130:21) 
    at apply (http://localhost:3000/packages/handlebars.js?c2b75d49875b4cfcc7544447aad117fd81fccf3b:276:24) 
    at invoke (http://localhost:3000/packages/handlebars.js?c2b75d49875b4cfcc7544447aad117fd81fccf3b:301:12) 
    at http://localhost:3000/packages/handlebars.js?c2b75d49875b4cfcc7544447aad117fd81fccf3b:365:30 
    at Object.Spark.labelBranch (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1171:14) 
    at branch (http://localhost:3000/packages/handlebars.js?c2b75d49875b4cfcc7544447aad117fd81fccf3b:355:20) 
    at http://localhost:3000/packages/handlebars.js?c2b75d49875b4cfcc7544447aad117fd81fccf3b:364:18 
    at Array.forEach (native) 
    at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?13ab483e8a3c795d9991577e65e811cd0b827997:130:11) 
    at template (http://localhost:3000/packages/handlebars.js?c2b75d49875b4cfcc7544447aad117fd81fccf3b:358:7) debug.js:41 
Exception from Deps recompute: Error: Can't create second landmark in same branch 
    at Object.Spark.createLandmark (http://localhost:3000/packages/spark.js?3a050592ceb34d6c585c70f1df11e353610be0ab:1226:13) 
    ...<snip>... 

這大約Can't create second landmark in same branch最後一個錯誤給我上通過其他職位,均與循環做了一大通,但是這僅僅是一個簡單的收集訪問。在堆棧跟蹤中有一些forEach調用,所以我嘗試了類似Meteor issue 281的解決方案,但都無濟於事。

流星約定的提示和解釋非常感謝。謝謝。

回答

5

我遇到了同樣的問題。

return user && user.emails[0].address; 

檢查,如果用戶是不確定的第一個(用戶& & ......)似乎已經做到了。

1

看一看流星用戶http://docs.meteor.com/#meteor_user

流星已經提供了登錄的用戶給你,讓你不必再去找他。

嘗試

Template.hello.userData = function() { 
    var user = Meteor.user(); 
    return user && user.emails[0].address; 
}; 
+0

不可以:即使在我給出的測試用例中,這也給出了相同的結果。此外,這對我的完整應用程序沒有幫助,因爲我實際上試圖訪問與已登錄的用戶不同的用戶。 – Trent

+1

我無法使用您通過簡單測試給出的測試用例來重現此問題用戶應用程序使用我建議的編輯。按照原樣使用您的代碼,我能夠重現未定義的「錯誤未捕獲的TypeError:無法讀取屬性」電子郵件。你確定你使用了我建議的代碼更改嗎?如果你是的話,你不應該得到未定義錯誤的電子郵件。 至於你對你的完整應用程序的幫助,你需要確保你正在發佈用戶,並做一個findOne,但不是與你的OP中的Meteor.userId()一樣,這將不起作用,因爲這是登錄用戶的ID。 – landland

+1

確保您的代碼在訪問屬性(如landland的代碼示例)之前檢查用戶的存在。即使用戶可能存在於數據庫中,它也可能不存在於客戶端集合中,但是如果在執行模板函數時數據尚未完成加載 – jrullmann

2

要設置所呈現的模板,並從服務器到達的數據之間的競爭條件。

這與期望數據在異步調用後立即可用相似;您必須等待回調才能執行以訪問響應。在Meteor的案例中,由於需要一段時間才能從服務器檢索數據,因此您必須確保預期的字段在使用之前已被填充,如@landland所示。

爲了進一步解釋競爭情況,大部分時間您的數據在模板呈現之前到達並且一切正常。但有時候,模板呈現時,服務器還沒有完成將用戶數據發佈到客戶端,因此您會收到錯誤消息。(這是@jrullmann在他的評論中描述的)。

此外,由於在完整的應用程序中,您訪問的用戶與您登錄的用戶不同,因此您需要明確發佈該用戶的信息。只有當前登錄的用戶信息由帳戶包自動發佈。