Meteor.logout()导致帮助程序重新运行

时间:2015-09-03 22:08:06

标签: meteor meteor-accounts

我想在我的应用程序中添加一个注销按钮,但事实证明这比我想象的要困难,因为在调用Meteor.logout之后会出现一个意外调用助手的情况。考虑以下简单的应用程序(you can find the complete code in this MeteorPad;我尽量保持尽可能短):

如果用户已登录,服务器将发布Tasks集合的内容。否则,它不会发布任何记录。

Meteor.publish('tasks', function() {
  if (this.userId) {
    return Tasks.find();
  } else {
    return null;
  }
});

有一个布局模板,用于处理登录/注销,订阅发布,并显示子模板(task):

<template name="layout">
  {{#if loggedInAndReady}}
    {{> task}}

    <button class="logout">Logout</button>
  {{else}}
    <button class="login">Login</button>
  {{/if}}
</template>

在此task模板中,有一个帮助器title,它使用Tasks.findOne()从订阅中检索任务,并在调用时写入日志:

<template name="task">
  {{description}}
</template>

Template.task.helpers({
  title: function() {
    console.log("task helper");
    Tasks.findOne();
  }
});

以下是问题: 当我退出时,loggedInAndReady将变为false,但仍会调用title模板的task帮助程序。但是,我不希望调用帮助器,因为我假设我试图在助手中获取的数据总是退出。除了注销和删除模板之间的短暂时间外,这种假设始终是正确的。

这些是您再次登录和退出时发生的步骤(您可以在上面链接的MeteorPad的开发控制台中看到此输出):

task template created
task helper
logging out
task helper <-- Why is this called? I'm already logged out.
task template destroyed

我知道当用户注销时,服务器上的tasks发布会再次以null作为新用户ID执行,这反过来会导致客户端上的帮助程序再次运行,因为结果集已更改(即变为空)。但是,此时已经知道帮助程序的结果将不再使用(之后模板被销毁)。

奇怪的是,当您登录时,重新加载页面,然后注销,它按预期工作(不再调用帮助程序):

task template created
task helper
logging out
task template destroyed

我是否误解了Meteor反应性概念的一部分,或者代码中是否存在错误?页面重新加载如何影响这样的帮助程序的执行?

1 个答案:

答案 0 :(得分:3)

您遇到竞争条件,您的用户往返时间略长于您的任务数据。您会发现Meteor.userId()的响应速度实际上比Meteor.user()更快,因为(我相信)它不需要第二次往返。

但是,这一切都不重要,因为您只需要向助手添加guard。辅助函数需要对其基础数据的变化具有弹性,因此您应该像这样重写它:

Template.task.helpers({
  title: function() {
    var task = Tasks.findOne();
    return task && task.title;
  }
});