我正試圖圍繞流星的反應性包裹我的頭。我知道,當模板中引用的被動數據源發生更改時,它會重新呈現頁面。我也明白什麼構成被動源(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