【问题标题】:Meteor - rendering the name of the owner in a list objectsMeteor - 在列表对象中呈现所有者的名称
【发布时间】:2014-04-06 10:54:23
【问题描述】:

我在尝试查找对象的所有者时遇到对象未找到错误 我正在尝试渲染。我正在循环浏览一组可以由用户更新或管理的视频剪辑。当我登录时代码工作正常,但是当我尝试使用它并注销时,我得到“队列任务中的异常:TypeError:无法读取 Object.Template.video_info 中未定义的属性 '_id'。创作者姓名"

我试图通过这样做来调试它:

console.log(this.owner);
var owner = Meteor.users.findOne(this.owner);
console.log(owner);

当我检查控制台日志时,我可以看到找到了正确的用户 ID,并且当我使用此 ID 手动运行 Meteor.users.findOne 时,我会返回一个用户对象。 Meteor 的计时有什么奇怪的地方阻止了这种情况发生吗?

更新:如果我在模板 creatorname 函数中添加一个 try...catch,则会记录 2 个错误,但模板仍然呈现... ???似乎这个模板被调用了两次,一次是没有准备好,一次是它。为什么会这样。

try...catch 块的示例:

  Template.video_info.creatorName = function () {
      try{
        var owner = Meteor.users.findOne(this.owner);
        if (owner._id === Meteor.userId())
          return "me";
        return displayName(owner);
      } catch (e){
        console.log(e);
      }
  };

此点下方的原始损坏代码

这是在我的 HTML 中:

<body>
  <div>
    {{> video_list}}
  </div>
</body>
<template name="video_list">
  <h1>Video List</h1>
  {{#each videos}}
    <ul>
      {{> video_info}}
    </ul>
  {{else}}
    No videos yet.
  {{/each}}
  <div class="footer">
    <button>Like!</button>
  </div>
</template>

<template name="video_info">
  <li class="video-list {{maybe_selected}}">
    <img src="{{image}}" />
    <div>
      <h3>{{title}}</h3>
      <p>{{description}}</p>
      <h4>{{creatorName}}</h4>
    </div>
  </li>
</template>

这是在我的 client.js 中

Meteor.subscribe("videos");

if (Meteor.isClient) {

  Template.video_list.videos = function() {
    return Videos.find({}, {sort: {title: 1}});
  };

  Template.video_list.events = {
    'click button': function(){
      Videos.update(Session.get('session_video'),{$inc: {likes: 1}});
    }
  }

  Template.video_info.maybe_selected = function() {
    return Session.equals('session_video', this._id) ? "selected" : "";
  }

  Template.video_info.events = {
    'click': function(){
      Session.set('session_video', this._id);
    }
  }

  Template.video_info.creatorName = function () {
    var owner = Meteor.users.findOne(this.owner);
    if (owner._id === Meteor.userId())
      return "me";
    return displayName(owner);
  };
}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

这是在我的 model.js 中

Videos = new Meteor.Collection("videos");

Videos.allow({
  insert: function (userId, video) {
    return false; // no cowboy inserts -- use createParty method
  },
  update: function (userId, video, fields, modifier) {
    if (userId !== video.owner)
      return false; // not the owner

    var allowed = ["title", "description", "videoid", "image", "start"];
    if (_.difference(fields, allowed).length)
      return false; // tried to write to forbidden field

    // A good improvement would be to validate the type of the new
    // value of the field (and if a string, the length.) In the
    // future Meteor will have a schema system to makes that easier.
    return true;
  },
  remove: function (userId, video) {
    // You can only remove parties that you created and nobody is going to.
    return video.owner === userId; //&& attending(video) === 0;
  }
});

var NonEmptyString = Match.Where(function (x) {
  check(x, String);
  return x.length !== 0;
});

var NonEmptyNumber = Match.Where(function (x) {
  check(x, Number);
  return x.length !== 0;
});

createVideo = function (options) {
  var id = Random.id();
  Meteor.call('createVideo', _.extend({ _id: id }, options));
  return id;
};

Meteor.methods({
  // options should include: title, description, x, y, public
  createVideo: function (options) {
    check(options, {
      title: NonEmptyString,
      description: NonEmptyString,
      videoid: NonEmptyString,
      image:NonEmptyString,
      start: NonEmptyNumber,
      _id: Match.Optional(NonEmptyString)
    });

    if (options.title.length > 100)
      throw new Meteor.Error(413, "Title too long");
    if (options.description.length > 1000)
      throw new Meteor.Error(413, "Description too long");
    if (! this.userId)
      throw new Meteor.Error(403, "You must be logged in");

    var id = options._id || Random.id();
    Videos.insert({
      _id: id,
      owner: this.userId,
      videoid: options.videoid,
      image: options.image,
      start: options.start,
      title: options.title,
      description: options.description,
      public: !! options.public,
      invited: [],
      rsvps: []
    });
    return id;
  },

});

///////////////////////////////////////////////////////////////////////////////
// Users

displayName = function (user) {
  if (user.profile && user.profile.name)
    return user.profile.name;
  return user.emails[0].address;
};

var contactEmail = function (user) {
  if (user.emails && user.emails.length)
    return user.emails[0].address;
  if (user.services && user.services.facebook && user.services.facebook.email)
    return user.services.facebook.email;
  return null;
};

【问题讨论】:

    标签: javascript mongodb meteor


    【解决方案1】:

    我想我已经找到了解决这个问题的方法。在阅读了 Meteor 中的缓存工作后,我发现了订阅模型以及它与流星 minimongo http://docs.meteor.com/#dataandsecurity 的关系。失败然后成功的原因是,在第一次加载时,数据仍被缓存在 minimongo 中。我目前正在检查帐户登录服务配置以检查用户数据是否已加载。我目前正在使用它,因为我找不到订阅 Metor 用户服务的方法,但我的猜测是 Accounts 登录服务将依赖于 Metor 用户集合。我目前的解决方案如下所示:

    if(Accounts.loginServicesConfigured()){
      var owner = Meteor.users.findOne(this.owner);
      if (owner._id === Meteor.userId())
        return "me";
      return displayName(owner);
    }
    

    目前这似乎工作正常。我仍在研究如何订阅此用户服务。我在寻找解决方案时发现了一些非常有用的参考

    【讨论】:

      【解决方案2】:

      当您注销时,应用程序可能不会将用户 ID 发布到客户端。您可以尝试在服务器上调用 find 方法并返回用户。或者使用不同的键进行查询/

      【讨论】:

      • 肯定推出用户ID。我用它来识别对象列表(因此会有多个用户 ID)。如果我将它包装在 try...catch 块中,它就会运行。我认为这与手术的时机有关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      相关资源
      最近更新 更多