Meteor JS:如何将Meteor.call的结果分配给变量?

时间:2013-12-30 07:45:08

标签: javascript collections meteor

我正在尝试将文档插入到彼此相关的集合中:PostsCommentsCategoriesCommentsCategories中的每个文档都必须包含PostId字段。

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

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

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

这是我的完整代码:

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);
  }
});

2 个答案:

答案 0 :(得分: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);
  }
});

现在,您可以在userId回调中添加submittedPosts.allow()字段:

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

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

答案 1 :(得分:0)

您可以使用Session来存储结果,因为Session是被动的,而客户端javascript是异步的,因此您无法使用return直接将结果分配给变量。

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

然而,为了插入帖子,最好只在回调中插入注释和类别,因为你没有在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);
    }
});

这样,如果结果是错误,则不会插入注释和类别。