Javascript 了解Meteor何时重新计算我的模板助手
我正试着用我的头脑去思考流星的反应性。我知道当模板中引用的被动数据源发生更改时,它会重新呈现页面。我还了解什么是反应源(会话、MongoDB游标等) 我很难理解的是所有这些对模板助手的“幕后”调用。除了反应性之外,似乎还有其他原因导致它们 特别是,在下面的代码中,我有一个Javascript 了解Meteor何时重新计算我的模板助手,javascript,mongodb,templates,meteor,Javascript,Mongodb,Templates,Meteor,我正试着用我的头脑去思考流星的反应性。我知道当模板中引用的被动数据源发生更改时,它会重新呈现页面。我还了解什么是反应源(会话、MongoDB游标等) 我很难理解的是所有这些对模板助手的“幕后”调用。除了反应性之外,似乎还有其他原因导致它们 特别是,在下面的代码中,我有一个friendRequests帮助程序,在单独访问/friends页面时,它会被重新计算两次有时三次。如果重新计算两次,DB查询将成功!如果重新计算三次,则第一个数据库访问(出于某些奇怪的原因)无法查询数据库,而后两个则成功 这是
friendRequests
帮助程序,在单独访问/friends
页面时,它会被重新计算两次有时三次。如果重新计算两次,DB查询将成功!如果重新计算三次,则第一个数据库访问(出于某些奇怪的原因)无法查询数据库,而后两个则成功
这是数据库失败时的堆栈跟踪:
// NOTE: imsolonely is one of the users that should be returned in the friendRequests
imsolonely's public key: undefined
debug.js:41 Exception in template helper: TypeError: Cannot read property 'profile' of undefined
at Object.Utils.getPublicKeyByUsername (http://localhost:3000/lib/utils.js?acf4e03d4c8a70819c26f8d2fd08caf7100768fe:79:22)
at Object.Utils.getFingerprintByUsername (http://localhost:3000/lib/utils.js?acf4e03d4c8a70819c26f8d2fd08caf7100768fe:88:24)
at http://localhost:3000/client/friends.js?dbec4a7537c9d0abf56a74489824969cb7baadfe:25:35
at Array.forEach (native)
at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?0a80a8623e1b40b5df5a05582f288ddd586eaa18:156:11)
at Object.Template.friendRequests.helpers.friendRequests (http://localhost:3000/client/friends.js?dbec4a7537c9d0abf56a74489824969cb7baadfe:22:7)
at http://localhost:3000/packages/blaze.js?77c0809654ee3a10dcd5a4f961fb1437e7957d33:2693:16
at http://localhost:3000/packages/blaze.js?77c0809654ee3a10dcd5a4f961fb1437e7957d33:1602:16
at Object.Spacebars.dot (http://localhost:3000/packages/spacebars.js?3c496d2950151d744a8574297b46d2763a123bdf:231:13)
at http://localhost:3000/client/template.friends.js?a2da726f6dad1aaecfdedfe216aa3378fff938b5:24:37
utils.js?acf4e03d4c8a70819c26f8d2fd08caf7100768fe:78 imsolonely's public key: {"profile":{"publicKey":"0404b4880129edc1ea2652dd1eff1c8728269874b9b0ace02cc90edcb449c3f3d716c2f8b79a5fe5695d52cd85aed228f977073538625e8e71f1cfd764766669b1"},"_id":"sXjzt7YHA8KTyAib5"}
utils.js?acf4e03d4c8a70819c26f8d2fd08caf7100768fe:78 imsolonely's public key: {"profile":{"publicKey":"0404b4880129edc1ea2652dd1eff1c8728269874b9b0ace02cc90edcb449c3f3d716c2f8b79a5fe5695d52cd85aed228f977073538625e8e71f1cfd764766669b1"},"_id":"sXjzt7YHA8KTyAib5"}
这也发生在我的许多(或全部,不确定)助手身上。它们在需要时被调用,因为用户未登录(并且模板未呈现,因此不应重新计算助手)
下面是一些代码:
client/friends.js
:
Template.friendRequests.helpers({
friendRequests:函数(){
//问题1:在我登录之后但在我完全登录之前,模板会被调用
//所以我需要这个电话。
如果(!Meteor.user())
返回Utils.notLoggedInErrorMsg;
//问题2:模板被调用了三次。第一次DB查询失败
//好像DB行不存在。接下来的2次它成功了。但它应该只存在
//打过一次电话。
var reqs=Friends.getFriendRequests(Utils.me());
_.每个(需求、功能(要素、it、列表){
检查(element.initiator,String);
//获取用户的指纹
element.fingerprint=Utils.getFingerprintByUsername(element.initiator);
});
退货要求;
},
});
client/friends.html
:
{{>friendRequests}
{{>searchForm}
我的朋友们
{{{各位朋友}
- {{this}}
{{/每个}}
好友请求
{{#如果friendRequests.length}
今天有人很受欢迎
{{{#每个friendRequests}
- 带有指纹的{{initiator}}{{fingerprint}}在{date}向您发送了一个请求李>
{{/每个}}
{{else}
对不起,现在没人喜欢你
{{/if}
lib/utils.js
:
Utils={
// ...
//其他东西
// ...
//@以字符串形式返回十六进制编码的公钥
getPublicKeyByUsername:函数(用户名){
var user=Meteor.users.findOne({username:username},{fields:{'profile.publicKey':1}});
log(用户名+'\'的公钥:'+EJSON.stringify(用户));
var pubKey=user.profile.publicKey;
返回公钥;
},
//注意:尚未使用,我在需要时直接使用了CryptoUtils函数
//
//@以十六进制编码字符串的形式返回指纹
getFingerprintByUsername:函数(用户名){
var pubKey=Utils.getPublicKeyByUsername(用户名);
var fingerprint=CryptoUtils.getPublicKeyFingerprint(pubKey);
返回指纹;
},
notLoggedInErrorMsg:“流星是愚蠢的,在我没有登录的时候叫这个。”,
}
如果重要的话,我正在使用iron:router
1.0.3包重定向到/friends
URL
如果您能澄清为什么/friendsrequests
帮助程序在看不见的情况下被重新计算,为什么在刷新/friends
页面时被重新计算两次、三次而不是一次,我们将不胜感激
谢谢,,
Alin一般来说,您应该期望您的助手会接到多次电话。如果在用户登录时呈现模板,而不等待数据发布,则助手可能会运行:
Friends
数据首次到达客户端时朋友
数据到达或被修改时你的第二个问题的答案可以在我的帖子上找到。简言之,您不能假设数据已到达客户端,因此您需要在呈现模板之前检查其存在性,或者需要在路由器中明确订阅。事实证明,my
waitOn
hook中存在错误。我没有返回任何东西,我只是进行Meteor.subscribe()
调用,而不是返回它们的数组。以下是修复DB异常的方法:
Router.configure({
layoutTemplate:“主布局”,
loadingTemplate:“正在加载”,
waitOn:函数(){
返回[
Meteor.subscribe('userData'),
Meteor.subscribe(“allUserData”),
Meteor.subscribe('UserProfiles'),
];
},
});
对于未定义的Meteor.user()
,我仍然没有一个好的解决方案。或者这也解决了问题
PS:谢谢@DavidWeldon帮我缩小范围 因此,我有一个
Router.configure()
设置默认布局,并为我所有代码中需要的Meteor.subscribe
调用设置一个waitOn
。我还有一个路由器.onBeforeAction
,可以重定向到具有不同布局的登录页面。我真的不喜欢我必须为Meteor.user()
签入几十个模板,而这些模板在Meteor.user()==false
时甚至没有呈现(或者至少不应该呈现)。另外,即使我要到处检查,我会返回什么?我猜