简体   繁体   English

Meteor重新启动时Meteor.users尚未准备好

[英]Meteor.users is not ready when Meteor restarts

When developing, everytime I save a file Meteor restarts (which is an excelent feature), however some pages have some validatons based on the user profile and they are redirected to landing page. 开发时,每次保存文件时,Meteor都会重新启动(这是一项出色的功能),但是某些页面会根据用户个人资料进行一些验证,并将它们重定向到登录页面。 I was checking and it seems that Meteor.users is not ready yet. 我正在检查,看来Meteor.users尚未准备好。 How can I sort it? 如何分类?

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

You won't get the Mereor.userId() immediately, there is a subtle delay for it's readiness. 您不会立即获得Mereor.userId() ,因为其准备工作会Mereor.userId()延迟。

You can use Tracker.autorun to track the readiness of Meteor.userId() . 您可以使用Tracker.autorun跟踪Meteor.userId()的准备情况。 Tracker.autorun allows a function to be called automatically whenever it's dependent reactive data source changes. Tracker.autorun允许函数在依赖的反应性数据源发生更改时自动被调用。

Simply speaking, Tracker.autorun() takes a function as input, runs this function and returns whenever the data source changes later on. 简而言之, Tracker.autorun()将一个函数作为输入,运行此函数并在以后数据源发生更改时返回。

In your case, you can use Tracker.autorun() for tracking the userId , since Meteor.user() and Meteor.userId() are reactive. 对于您的情况,可以使用Tracker.autorun()来跟踪userId ,因为Meteor.user()Meteor.userId()是反应性的。 In componentDidMount() call Tracker.autorun() and save the userId elsewhere when it changes. componentDidMount()调用Tracker.autorun()并将userId更改时保存在其他位置。

Hope following code snippet helps: 希望以下代码段对您有所帮助:

componentDidMount() {
        var context = this;

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

Using Rahman's answer, you could simply write the code in componentDidMount like this: 使用Rahman的答案,您可以像这样在componentDidMount编写代码:

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

Arrow function uses its container context as this . Arrow函数将其容器上下文用作this

You can create a function which takes an callback and execute it only when client is ready with all the data needed. 您可以创建一个接受回调并仅在客户端准备好所有需要的数据后才执行的函数。

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

Then use this 然后用这个

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

In order to make sure that you have Meteor.userId() when you run this method. 为了确保您在运行此方法时具有Meteor.userId() You have to make sure to render the template only when the Meteor.userId() is present. 您必须确保仅在存在Meteor.userId()时才呈现模板。 To do that you can use top level layout template and do something like this 为此,您可以使用顶层布局模板并执行类似的操作

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

Hope this will help. 希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM