【问题标题】:Meteor.users is not ready when Meteor restartsMeteor 重启时 Meteor.users 尚未准备好
【发布时间】:2018-06-05 18:26:28
【问题描述】:

在开发时,每次我保存文件时,Meteor 都会重新启动(这是一个很棒的功能),但是有些页面有一些基于用户配置文件的验证,它们会被重定向到登录页面。我正在检查,似乎 Meteor.users 还没有准备好。如何排序?

SpecialController = MainController.extend({
  onBeforeAction: function(){
    const user = Meteor.users.findOne({_id: Meteor.userId()});
    if (user && user.profile.internalStatus == "valid") {
      this.next();
    } else {
     // the routers is sending here but it shouldn't.
      Router.go('dashboard');
    }
  }
});

【问题讨论】:

  • Meteor.userId 在重启时不会立即准备好,需要一小段时间才能准备好。不好的是,渲染通常已经发生了。好消息是,它是反应式的,因此您可以在其上的模板中收听或将 Tracker 与您的路由器结合使用。如果 Iron 路由器支持 before-rendered-hooks,你也可以使用它们来监听用户 ID,并且只有在 userId 出现时才继续路由。
  • userId 没问题,我的问题是 Meter.users,还没准备好。我试图使用waitOn,但它不起作用。

标签: javascript meteor iron-router meteor-accounts


【解决方案1】:

您可以创建一个接受回调的函数,并仅在客户端准备好所需的所有数据时执行它。

Meteor.runWithFullUser = function(cb) {
  Tracker.autorun((c) => {
    const user = Meteor.user();
    if(typeof user.profile !== 'undefined') {
      cb();
      c.stop();
    }
  });
}

那就用这个

SpecialController = MainController.extend({
  onBeforeAction: function(){
    Meteor.runWithFullUser(() => {
      const user = Meteor.users.findOne({_id: Meteor.userId()});
      if (user && user.profile.internalStatus == "valid") {
        this.next();
      } else {
       // the routers is sending here but it shouldn't.
        Router.go('dashboard');
      }
    });
  }
});

为了确保您在运行此方法时拥有Meteor.userId()。您必须确保仅在存在 Meteor.userId() 时才呈现模板。为此,您可以使用顶级布局模板并执行类似的操作

<template name="layout">
  ...
  {{#if currentUser}}
    ...
  {{else}}
    {{> appLayout}}
  {{/if}}
</template>

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您不会立即收到Mereor.userId(),它准备就绪时会有一个微妙的延迟。

    您可以使用Tracker.autorun 来跟踪Meteor.userId() 的准备情况。 Tracker.autorun 允许在依赖的响应式数据源发生更改时自动调用函数。

    简单地说,Tracker.autorun() 将一个函数作为输入,运行该函数并在以后数据源更改时返回。

    在您的情况下,您可以使用Tracker.autorun() 来跟踪userId,因为Meteor.user()Meteor.userId() 是被动的。在componentDidMount() 中调用Tracker.autorun() 并在更改时将userId 保存在别处。

    希望以下代码 sn-p 有所帮助:

    componentDidMount() {
            var context = this;
    
            Tracker.autorun(function() {
                let userId = Meteor.userId();
                if (userId != undefined) {
                    context.setState({ userId: userId });
                }
            });
        }
    

    【讨论】:

      【解决方案3】:

      使用 Rahman 的答案,您可以像这样简单地在 componentDidMount 中编写代码:

      componentDidMount() {
         Tracker.autorun(() => {
            let userId = Meteor.userId();
            if (userId != undefined) {
               this.setState({ userId: userId });
            }
         });
      }
      

      箭头函数将其容器上下文用作this

      【讨论】:

        猜你喜欢
        • 2015-04-30
        • 2016-01-24
        • 1970-01-01
        • 2017-12-19
        • 1970-01-01
        • 2017-09-01
        • 2016-10-10
        • 1970-01-01
        • 2019-08-14
        相关资源
        最近更新 更多