模板上的以下简单函数通常会失败,因为user
对象未定义,即使我已登录:
Template.hello.userData = function() {
var user = Meteor.users.findOne(Meteor.userId());
return user.emails[0].address;
};
复制很容易:
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中的解决方案,但没有用。
非常感谢Meteor惯例的提示和解释。感谢。
答案 0 :(得分:5)
我遇到了同样的问题。
return user && user.emails[0].address;
首先检查用户是否未定义(用户&amp;&amp; ...)似乎已完成。
答案 1 :(得分:2)
您正在渲染的模板与从服务器到达的数据之间设置竞争条件。
这类似于期望在异步调用后立即可用的数据;你必须等待执行回调才能访问响应。在Meteor的情况下,由于从服务器检索数据需要一些时间,因此必须确保在使用之前填充了预期的字段,正如@landland建议的那样。
为了进一步解释竞争条件,大部分时间是在渲染模板之前数据到达并且一切正常。但有时,在模板呈现时服务器尚未完成将用户数据发布到客户端,因此您会收到错误。 (这是@jrullmann在评论中描述的内容。)
此外,由于您在完整的应用程序中访问的用户与登录的用户不同,因此您需要明确发布该用户的信息。只有当前登录用户的信息由帐户包自动发布。
答案 2 :(得分:1)
查看Meteor用户http://docs.meteor.com/#meteor_user
Meteor已经为您提供了登录用户,因此您无需再次找到他。
尝试
Template.hello.userData = function() {
var user = Meteor.user();
return user && user.emails[0].address;
};