0

我目前正在尝试通过在用户单击其他页面时存储 userId、Meteor.Router.page() 和时间戳来记录流星应用程序中的用户页面视图。

//userlog.js
Meteor.methods({
  createLog: function(page){
    var timeStamp = Meteor.user().lastActionTimestamp;
    //Set variable to store validation if user is logging in
    var hasLoggedIn = false;
    //Checks if lastActionTimestamp of user is more than an hour ago
    if(moment(new Date().getTime()).diff(moment(timeStamp), 'hours') >= 1){
      hasLoggedIn = true;
    }
      console.log("this ran");

    var log = {
      submitted: new Date().getTime(),
      userId: Meteor.userId(),
      page: page,
      login: hasLoggedIn
    }

    var logId = Userlogs.insert(log);

    Meteor.users.update(Meteor.userId(), {$set: {lastActionTimestamp: log.submitted}});
    return logId;
  }
});

//router.js This method runs on a filter on every page
'checkLoginStatus': function(page) {
    if(Meteor.userId()){
      //Logs the page that the user has switched to
      Meteor.call('createLog', page);
      return page;
    }else if(Meteor.loggingIn()) {
      return 'loading';
    }else {
      return 'loginPage';
    }
  }

但是,这不起作用,最终会递归创建用户日志。我相信这是因为我在路由器过滤方法中做了一个 Collection.find 。有没有人可以解决这个问题?

4

1 回答 1

1

当您更新Meteor.users和设置lastActionTimestamp时,Meteor.user将更新并将失效信号发送到依赖它的所有反应上下文。如果Meteor.user在过滤器中使用,则该过滤器和所有连续的过滤器,包括checkLoginStatus将重新运行,从而导致循环。

我发现的最佳实践:

  1. 尽量避免在过滤器中使用反应式数据源。

  2. 尽可能使用Meteor.userId(),而不是Meteor.user()._id因为前者不会在用户对象的属性更改时触发失效。

  3. 订购您的过滤器,以便它们首先使用最频繁更新的反应数据源运行。例如,如果您有一个trackPage需要用户的过滤器,让它在另一个过滤器调用之后运行,requireUser以便您在跟踪之前确定您有一个用户。否则,如果您首先跟踪,然后检查用户,然后Meteor.logginIn从更改falsetrue,您将再次跟踪页面。

这是我们切换到meteor-mini-pages而不是Meteor-Router的主要原因,因为它更容易处理响应式数据源。过滤器可以redirect,它可以stop()让路由器运行等。

最后,cmather 和其他人正在开发一种新的路由器,它是迷你页面和 Meteor.Router 的合并。它将被称为 Iron Router,我建议在它推出后使用它!

于 2013-07-12T06:42:12.880 回答