Вопрос

I'm using the dev branch of iron-router and I'm having trouble using the waitOn option for my profile route. My route/page is where I show the currently logged in user's profile information such as:

  • Full Name/Username
  • Profile Picture
  • Description etc.

To get these (additional fields) I had to create a publication on the server as described in the Meteor Docs:

Meteor.publish("userData", function () {
    if (this.userId) {
        return Meteor.users.find({_id: this.userId}, {fields: {services: true}});
    } else {   
        this.ready();
    }
});

Now when I'm routed to my profile page I can get the extra information I requested (i.e. the services object) but that doesn't happen if I stay on the page and refresh my browser. So I thought this has to do with the timing of data being made available, according to Tom Coleman's comment.

I remembered I saw the waitOn option in iron-router so I tried to use it but it didn't change anything. So I'm guessing there is something I have misunderstood. I've structured my code according to the Discover Meteor book's suggestion and here is what I've done.

In server/app.js

Meteor.publish("userData", function () {
    if (this.userId) {
        return Meteor.users.find({_id: this.userId}, {fields: {services: true}});
    } else {   
        this.ready();
    }
});

In client/main.js

Meteor.subscribe("userData");

In client/views/profile/view.js I created the following template helper to get the full name of the user. (I know it's ugly!)

 Template.profile.helpers({
     fullName: function(){
     var currentUser = Meteor.user();       
     if(currentUser.services.google && currentUser.services.google.name)
         return currentUser.services.google.name;
     else if(currentUser.services.facebook && currentUser.services.facebook.name)
         return currentUser.services.facebook.name;
     else
         return currentUser.username;
     }  
  });

In lib/router.js

this.route('profile', {
    path: '/profile',
    onAfterAction: function(){
       Session.set("active_link", "profile");
    },
    waitOn: function () {
       return Meteor.subscribe('userData');
    }
 });

Adding the waitOn option above didn't change anything. Here is the error I get when I refresh my browser while still on the profile page. However, moving from another page to the profile page does not generate this error.

Exception from Deps recompute function: TypeError: Cannot read property 'google' of undefined
at Object.Template.profile.helpers.fullName (http://localhost:3000/client/views/profile/view.js?cc44954615a9c4eecd3d622d73a56599f483e44a:4:26)
at http://localhost:3000/packages/ui.js?b8fc4eba097393a5ae3f39738758c1a4e16d7b87:2787:23
at Spacebars.call (http://localhost:3000/packages/spacebars.js?dad2d487bcc43e537226e528539ce6389ad6ca4e:167:18)
at Spacebars.mustacheImpl (http://localhost:3000/packages/spacebars.js?dad2d487bcc43e537226e528539ce6389ad6ca4e:104:25)
at Object.Spacebars.mustache (http://localhost:3000/packages/spacebars.js?dad2d487bcc43e537226e528539ce6389ad6ca4e:108:39)
at http://localhost:3000/client/views/profile/template.view.js?7be9db8e2aaaba4e5c4c6e472cf2be15d26dcae1:54:24
at http://localhost:3000/packages/ui.js?b8fc4eba097393a5ae3f39738758c1a4e16d7b87:2286:21
at http://localhost:3000/packages/deps.js?9ff43a2bc56a25afccffa154c66253273407b6e5:347:45
at Object.Meteor._noYieldsAllowed (http://localhost:3000/packages/meteor.js?0f5145b6aeebbdfecdf65c9cb41449149646e99b:551:10)
at null._func (http://localhost:3000/packages/deps.js?9ff43a2bc56a25afccffa154c66253273407b6e5:347:14) 
Это было полезно?

Решение

When you hit refresh, meteor will start the login process again. If you are on a page which assumes the user is logged in, you will get a Deps error because Meteor.user() will return undefined. Here are some things you can experiment with:

  1. What happens if you just remove the else clause in your userData publication? It seems like indicating that the publication is ready is exactly not what you want if you are trying to wait on the data when the user is logging in.

  2. Use a before hook to catch the case where the user isn't logged in and do something useful like show a 'loading' or a 'signin' page, instead of immediately rendering whatever page was requested.

  3. Add a guard to your fullName helper (this is common practice whenever you see a Deps error). Just have it return an empty string if the user isn't logged in. Once the user is logged in, the function should get evaluated again and return the correct result.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top