我正试图围绕流星的反应性包裹我的头。我知道,当模板中引用的被动数据源发生更改时,它会重新呈现页面。我也明白什么构成被动源(Session,MongoDB游标等)。了解流星何时重新计算我的模板帮手
我无法理解的是所有这些“背后”打电话给我的模板助手。似乎有超过反应性导致他们。
特别是,在下面的代码,我有一个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: function() {
// Problem 1: The template gets called right after I log in but before I am fully logged in
// so I need this call here.
if(!Meteor.user())
return Utils.notLoggedInErrorMsg;
// Problem 2: The template gets called three times. The first time fails the DB query
// as if the DB row did not exist. The next 2 times it succeeds. But it should only be
// called once.
var reqs = Friends.getFriendRequests(Utils.me());
_.each(reqs, function(element, it, list) {
check(element.initiator, String);
// Get the user's fingerprint
element.fingerprint = Utils.getFingerprintByUsername(element.initiator);
});
return reqs;
},
});
client/friends.html
:
<template name="friends">
{{> friendRequests}}
{{> searchForm}}
<h2>My friends</h2>
<ul>
{{#each friends}}
<li>{{this}}</li>
{{/each}}
</ul>
</template>
<template name="friendRequests">
<h2>Friend requests</h2>
{{#if friendRequests.length}}
<p>Someone's popular today!</p>
<ul>
{{#each friendRequests}}
<li><b>{{initiator}}</b> with fingerprint <pre style="display: inline">{{fingerprint}}</pre> sent you a request on <em>{{date}}</em>. <a href="#">Accept <b>{{initiator}}</b> as a friend?</a></li>
{{/each}}
</ul>
{{else}}
<p>Sorry, nobody likes you right now.</p>
{{/if}}
</template>
lib/utils.js
:
Utils = {
// ...
// other stuff
// ...
// @return a hex-encoded public key as a string
getPublicKeyByUsername: function (username) {
var user = Meteor.users.findOne({ username: username }, { fields: { 'profile.publicKey': 1 } });
console.log(username + '\'s public key: ' + EJSON.stringify(user));
var pubKey = user.profile.publicKey;
return pubKey;
},
// NOTE: not used yet, i used the CryptoUtils function directly when I needed it
//
// @return the fingerprint as a hex-encoded string
getFingerprintByUsername: function (username) {
var pubKey = Utils.getPublicKeyByUsername(username);
var fingerprint = CryptoUtils.getPublicKeyFingerprint(pubKey);
return fingerprint;
},
notLoggedInErrorMsg: 'Meteor is being silly and calling this when I\'m not logged in.',
}
如果重要,我使用iron:router
1.0.3包重定向到/friends
URL。
任何澄清为什么friendRequests
助手正在重新计算,为什么它有时重新计算两次,有时三次,而不是一次当我刷新/friends
页将不胜感激!
谢谢 阿林
因此,我确实有一个'Router.configure()',它设置了默认布局,并且在所有**代码所需的所有'Meteor.subscribe'调用中都有一个'waitOn'。我还有一个'Router.onBeforeAction',它可以重定向到一个*版本不同的登录页面。当Meteor.user()== false时,我甚至不喜欢在'Meteor.user()'模板中检查数十个模板,当这些模板甚至不被渲染时(或者至少不应该渲染) '。 – 2014-12-02 20:27:22
另外,即使我到处检查,我会返回什么?我猜测null是一个坏主意。那么,我是否会为每个模板助手构造并返回该助手类型的虚拟对象?没有更好的方法来做到这一点? – 2014-12-02 20:27:41
此外,守卫的东西可能是可接受的简单代码,如'var post = Posts.findOne(); return posts && posts.id;'但是,它使复杂的简单/线性代码在返回之前需要稍微处理DB数据。编程开销将被添加到您编写的每个帮助程序以及您在该帮助程序中查询的每个集合。我希望有一个Meteor特有的方法来确保在某些帮助程序中你有:** 1。** Meteor.user()'始终是登录用户的ID。 ** 2。**当数据在那里并且查询正确时,数据库查询不应该因为不好的原因而失败。 – 2014-12-02 20:35:27