【问题标题】:Meteor JS: How do I assign the results of Meteor.call to a variable?Meteor JS:如何将 Meteor.call 的结果分配给变量?
【发布时间】:2013-12-31 10:08:46
【问题描述】:

我正在尝试将文档插入到相互关联的集合中:PostsCommentsCategoriesCommentsCategories 中的每个文档都必须有一个 PostId 字段。

我创建了一个名为insertSamplePost 的方法,它应该在将文档插入Posts 后返回帖子的ID。我已将此方法调用分配给如下变量:

var postId = Meteor.call('insertSamplePost', samplePost, function(error, id) {
  if (error) {
    console.log(error);
  } else {
    return id;
  }
});

但是,当我稍后尝试使用 postId 插入相关的 cmets 和类别时,它似乎未定义!有谁知道发生了什么?

这是我的完整代码:

if (Meteor.isClient) {
  Template.post.events({
    'click .new-sample-post' : function (e) {
      var samplePost = {
        title: "This is a title",
        description: "This is a description"
      };

      // Insert image stub
      var postId = Meteor.call('insertSamplePost', samplePost, function(error, id) {
        if (error) {
          console.log(error);
        } else {
          return id;
        }
      });

      // This returned undefined. :-()
      console.log(postId);

      var sampleComment = {
        body: "This is a comment",
        postId: postId
      };

      var sampleCategory = {
        tag: "Sample Category",
        postId: postId
      };

      Comments.insert(sampleComment);
      Categories.insert(sampleCategory);
    }
  });
}

// Collections
Posts = new Meteor.Collection('posts');
Comments = new Meteor.Collection('comments');
Categories = new Meteor.Collection('categories');

// Methods
Meteor.methods({
  insertSamplePost: function(postAttributes) {
    var post = _.extend(postAttributes, {
      userId: "John Doe",
      submitted: new Date().getTime()
    });

    return Posts.insert(post);
  }
});

【问题讨论】:

    标签: javascript collections meteor


    【解决方案1】:

    当你这样做时:

    var myVar = Meteor.call("methodName", methodArg, function(error, result) {
      return result;
    }
    

    您的myVar 变量实际上将是Meteor.call() 返回的任何内容,而不是您的回调函数返回的内容。相反,您可以做的是:

    var postId;
    Meteor.call('insertSamplePost', samplePost, function(error, id) {
      if (error) {
        console.log(error);
      } else {
        postId = id;
      }
    });
    

    但是,正如 Akshat 所提到的,当回调函数实际运行并异步设置 postId 时,您对其他集合的 insert 调用已经运行。

    如果您完全避免使用服务器方法,此代码实际上会更简单一些 - 您可以在集合的 allow 回调中修改文档:

    Template.post.events({
      'click .new-sample-post' : function (e) {
        var samplePost = {
          title: "This is a title",
          description: "This is a description"
        };
    
        var postId = Posts.insert(samplePost);
    
        var sampleComment = {
          body: "This is a comment",
          postId: postId
        };
    
        var sampleCategory = {
          tag: "Sample Category",
          postId: postId
        };
    
        Comments.insert(sampleComment);
        Categories.insert(sampleCategory);
      }
    });
    

    现在您可以在Posts.allow() 回调中添加userIdsubmitted 字段:

    Posts.allow({
      insert: function(userId, doc) {
        doc.userId = userId;
        doc.submitted = new Date().getTime();
        return true;
      }
    });
    

    如果您愿意,您仍然可以在第一个 insert 的回调中执行两个辅助 inserts,以使操作更加原子(换句话说,确保辅助 inserts如果第一个 insert 失败,则不会发生)。

    【讨论】:

    • 哦,太好了,我确实知道 Posts.allow() 回调!为什么完全避免服务器方法调用更好?
    • 好吧,看看我编辑的代码 - 如果你不想这样做,你不必在回调中使用这种方法做你的辅助inserts。使用服务器方法调用并没有什么问题,但是这个特定的操作可以只用普通的数据库 API 来完成。在我看来,它使代码更具可读性。
    • 糟糕,我的意思是我知道 Posts.allow() 回调。错误的错字。谢谢!
    【解决方案2】:

    您可以使用Session 来存储结果,因为Session 是响应式的,而客户端javascript 是异步的,因此您不能直接使用return 将结果分配给变量。

    所以你得到 undefined 的原因是因为 Meteor.call 的结果是在回调中给出的。回调将在很久以后产生结果,并且在它返回结果时,其余代码已经运行。这就是为什么使用 Session 是个好主意,因为您可以在模板助手中使用它。

    但是,对于插入帖子,最好在回调本身中插入 cmets 和类别,因为您没有在 html 中显示结果。

    Meteor.call('insertSamplePost', samplePost, function(error, postId) {
        if (error) {
            console.log(error);
        } else {
          var sampleComment = {
            body: "This is a comment",
            postId: postId
          };
    
          var sampleCategory = {
            tag: "Sample Category",
            postId: postId
          };
    
          Comments.insert(sampleComment);
          Categories.insert(sampleCategory);
        }
    });
    

    这样,如果结果是错误的,评论和类别将不会被插入。

    【讨论】:

    • 嗯,有道理,谢谢!我刚刚尝试的另一种方法是生成一个唯一对象var postId = new Meteor.Collection.ObjectID()._str,并将其用作新帖子以及 cmets 和类别的属性。这似乎也有效。
    猜你喜欢
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多