I'm using the profile field in Meteor.users system defined collection to store information about the last message user read on every communication channel with the following structure:
profile : {
lastMsgRead : [
{channelId: 'YYEBNEI7894K', messageCreatedAt: '14578970667"}
{channelId: 'GERYUE789774', messageCreatedAt: '14578999845"}
]
}
I discovered that reading lastMsgRead field fails because of on the client the array in still empty at the time of read. I correctly publish this field to the client through:
Meteor.publish(null, function() {
return Meteor.users.find({}, {fields: {_id: 1, username: 1, emails: 1, profile :1}});
and I read its value from a client library located in the lib directory, in this way:
var chHistory = Meteor.user().profile.lastMsgRead;
Debugging my code it looks like the changes I make to the profile field have not been propagated to all the client at the time I read them. So I need to wait for the subscription Meteor.users gets ready, but I don't have its handle ─ you get this automatically from the framework.
How can I wait for the Meteor.users subscription gets ready?
Because meteor doesn't provide you with a handle for the current user's subscription, there isn't an obvious way to wait on the data. Here are some options:
use a guard
The typical way to handle this problem is to add guards to your code. In your template(s) which are experiencing this issue you could write something like:
var user = Meteor.user();
var lastMsgRead = user && user.profile && user.profile.lastMsgRead;
If you find you write that code a lot, you could factor it out into a shared function:
var extractProfileValue = function(key) {
var user = Meteor.user();
return user && user.profile && user.profile[key];
};
And use it like this:
var lastMsgRead = extractProfileValue('lastMsgRead');
show a spinner
You can test for the existence of the user's profile in the template itself:
<template name='myTemplate'>
{{#unless currentUser.profile}}
// show spinner or loading template here
{{else}}
// rest of template here
{{/unles}}
</template>
If you want this experience on all of your pages, you could add it to your layout template(s).
redundant publisher
WARNING: I have not tried this
One way to get a user's subscription handle is just to add a redundant publisher and subscribe to it:
Meteor.publish('myProfile', function() {
return Meteor.users.find(this.userId, {fields: {profile: 1}});
});
Then in your router:
waitOn: function () {
return Meteor.subscribe('myProfile');
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With