【问题标题】:How to properly use iron-router's waitOn route option?如何正确使用 Iron-router 的 waitOn 路由选项?
【发布时间】:2014-03-24 06:16:58
【问题描述】:

我正在使用 iron-routerdev 分支,但在为我的 profile 路由使用 waitOn 选项时遇到问题。我的路线/页面是我显示当前登录用户的个人资料信息的地方,例如:

  • 全名/用户名
  • 个人资料图片
  • 描述等

要获得这些(附加字段),我必须按照Meteor Docs 中的说明在服务器上创建一个发布:

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

现在,当我转到我的 个人资料 页面时,我可以获得我请求的额外信息(即 services 对象),但如果我留下来就不会发生这种情况在页面上并刷新我的浏览器。所以我认为这与提供数据的时间有关,根据Tom Coleman's comment

我记得我在 Iron-router 中看到了 waitOn 选项,所以我尝试使用它,但它并没有改变任何东西。所以我猜我误解了一些东西。我根据Discover Meteor 本书的建议构建了我的代码,这就是我所做的。

server/app.js

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

client/main.js

Meteor.subscribe("userData");

client/views/profile/view.js 中,我创建了以下模板助手来获取用户的全名。 (我知道这很丑!)

 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;
     }  
  });

lib/router.js

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

添加上面的waitOn 选项并没有改变任何东西。这是我在个人资料页面上刷新浏览器时遇到的错误。但是,从另一个页面移动到 个人资料 页面并不会生成此错误。

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) 

【问题讨论】:

    标签: meteor iron-router


    【解决方案1】:

    当您点击刷新时,meteor 将再次启动登录过程。如果您在假设用户已登录的页面上,您将收到Deps 错误,因为Meteor.user() 将返回undefined。以下是您可以尝试的一些方法:

    1. 如果您只删除 userData 发布中的 else 子句,会发生什么情况?如果您在用户登录时尝试等待数据,似乎表明发布已准备就绪并不是您想要的。

    2. 使用before hook 捕获用户未登录的情况并执行一些有用的操作,例如显示“正在加载”或“登录”页面,而不是立即呈现请求的任何页面。

    3. 为您的 fullName 助手添加一个守卫(当您看到 Deps 错误时,这是​​常见的做法)。如果用户未登录,只需让它返回一个空字符串。用户登录后,该函数应再次评估并返回正确的结果。

    【讨论】:

    • 感谢@David 的帮助,我按照上面列出的顺序尝试了您的建议,但事实证明 #3 是正确的做法。我只是检查了currentUser.services 是否可用,如果不只是返回currentUser.username,它在Meteor.user() 中很容易获得。 #1 我尝试删除 this.ready() 部分,但没有任何改变。 #2 我已经有一个 before 钩子,可以将用户重定向到带有登录链接的公共页面,所以这也没有帮助。但是#3为我做到了。谢谢!
    猜你喜欢
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 2015-07-07
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多