更改配置文件字段时如何等待 Meteor.users

How to wait on Meteor.users when changing profile field

我正在使用 Meteor.users 系统定义的集合中的配置文件字段来存储有关用户在具有以下结构的每个通信渠道上阅读的最后一条消息的信息:

profile : {
    lastMsgRead : [
        {channelId: 'YYEBNEI7894K', messageCreatedAt: '14578970667"}
        {channelId: 'GERYUE789774', messageCreatedAt: '14578999845"}
    ]
}

我发现读取 lastMsgRead 字段失败是因为客户端上的数组在读取时仍然是空的。 我通过以下方式正确地将此字段发布给客户端:

Meteor.publish(null, function() {
    return Meteor.users.find({}, {fields: {_id: 1, username: 1, emails: 1, profile :1}});

然后我从位于 lib 目录中的客户端库读取它的值,这样:

var chHistory = Meteor.user().profile.lastMsgRead;

调试我的代码时,我对配置文件字段所做的更改在我阅读它们时似乎尚未传播到所有客户端。所以我需要等待订阅 Meteor.users 准备就绪,但我没有它的句柄 ─ 你会自动从框架中获取它。

如何等待 Meteor.users 订阅准备就绪?

你需要再读一遍http://docs.meteor.com/#/full/meteor_user

On the client, this will be the subset of the fields in the document that are published from the server (other fields won't be available on the client). By default the server publishes username, emails, and profile (writable by user). SeeMeteor.users for more on the fields used in user documents.

您可以添加一个助手来 return 数据。

我也会删除您的出版物,因为它已经由框架处理。

Meteor.user().profile.blah

您的出版物公开了太多不必要的数据。你应该只发布你需要的。 Meteor.user() returns 如果用户已登录,则为用户对象。在您的 null 出版物中,您使用 this.userId 进行过滤。您可以在模板级别或使用 Iron Router 等待此发布。

因为 meteor 没有为您提供当前用户订阅的句柄,所以没有明显的方法来等待数据。以下是一些选项:

使用守卫

处理此问题的典型方法是将 guards 添加到您的代码中。在遇到此问题的模板中,您可以这样写:

var user = Meteor.user();
var lastMsgRead = user && user.profile && user.profile.lastMsgRead;

如果您发现自己经常编写该代码,则可以将其提取到一个共享函数中:

var extractProfileValue = function(key) {
  var user = Meteor.user();
  return user && user.profile && user.profile[key];
};

并像这样使用它:

var lastMsgRead = extractProfileValue('lastMsgRead');

显示微调器

您可以在模板本身中测试用户个人资料是否存在:

<template name='myTemplate'>
  {{#unless currentUser.profile}}
    // show spinner or loading template here
  {{else}}
    // rest of template here
  {{/unles}}
</template>

如果您希望在所有页面上都有这种体验,您可以将其添加到您的布局模板中。

冗余发布者

警告:我还没有试过这个

获取用户订阅句柄的一种方法是添加冗余发布者并订阅它:

Meteor.publish('myProfile', function() {
  return Meteor.users.find(this.userId, {fields: {profile: 1}});
});

然后在您的路由器中:

waitOn: function () {
  return Meteor.subscribe('myProfile');
}

由于您使用的是 null 或 "automatic" 发布,因此有一个非常简单的解决方法可以解决此问题,那就是向您的应用程序添加 meteorhacks:fast-render。它将发送所有自动发布的数据以及应用程序的初始 html,以便在页面加载后立即可用。