2014-01-07 145 views
2

这里是我的问题:流星JS:如何防止使用Meteor.call插入集合时的双重渲染?

在一个模板事件处理程序,我使用Meteor.call()调用一个方法来将文档插入集合。

由于某些原因,这会导致关联的模板呈现两次而不是一次。如果我在事件处理程序中直接使用Collection.insert(),则该模板只会呈现一次。我很困惑它为什么会渲染两次。数据更改时,如何防止模板呈现两次?

这里是我的代码:

Posts = new Meteor.Collection('posts'); 

if (Meteor.isClient) { 
    Template.postItem.rendered = function(e){ 
    console.log("This was rendered"); 
    } 

    Template.postsList.helpers({ 
    posts: function() { 
     return Posts.find(); 
    } 
    }); 

    Template.postsList.events({ 
    'submit form' : function (e) { 
     e.preventDefault(); 

     var post = { 
     title: $(e.target).find('[name=title]').val(), 
     } 

     // This causes double render 
     Meteor.call('post', post, function(error, id){ 
     if (error) { 
      console.log(error); 
     } 
     }); 

     // This causes only a single render 
     //Posts.insert(post); 
    } 
    }); 
} 

Meteor.methods({ 
    post: function(attrs) { 
    return Posts.insert(attrs); 
    } 
}); 

回答

0

这是一个众所周知的问题。关于这个问题,您可以阅读unofficial FAQ(为什么我有时会在延迟补偿方法中看到文档的两个副本?)。

我个人通过在方法中生成id(作为插入文档的哈希加上一点随机盐作为参数传递给冷静偏执狂)并在客户端和服务器上执行具有相同ID的插入来解决此问题。

+0

哦,孩子,这是令人沮丧的。我刚刚尝试了提前生成ID作为发送哈希的一部分的建议。这种工作,直到我做一些事情,如在服务器上添加一个时间戳文件,如'submit:new Date()。getTime()'。然后它会再次渲染两次。 “随机盐”是什么意思? – Chanpory

+0

@Chanpory我的意思是: 1.我的方法有额外的参数'randomSeed'(它是可选的,btw) 2.然后,在它创建要插入的对象之后,它通过以下代码行生成id: var id = Random.create([user._id,text,randomSeed]).id(); 3.然后它对集合执行“插入”操作。你可以尝试'upsert' - 不知道 方法存根内有什么区别。 – yeputons

+0

这个问题有没有更新? –

0

我没有发现任何问题的GitHub或SO回答解决了这个问题,所以我砍死我自己的解决方法(至少目前如此):

// Insert if recent comment from other user 
function _insertComment(){ 
    let doc = { //.. 
    }; 

    let commentId = Comments.insert(doc, (error, _id) => { 
     if (error) { console.log(error) } 
     else { return _id } 
    }); 
    let userId = Meteor.users.update({_id: self.userId}, {$push: {comments: commentId}}); 
    let pId = Projects.update({_id: projectId}, {$push: {comments: commentId}}); 

    throw new Meteor.Error('success', 'Sent!'); 
} 

// Update comment content array for same user 
function _updateComment(){ 
    let recentComment = Comments.find({projectId: projectId}, {sort: {createdAt: -1}}).fetch(); 
    let commentId = Comments.update({_id: recentComment[0]['_id']}, {$push: {content: comment}}); 
    throw new Meteor.Error('success', 'Sent!'); 
} 

我面对这个问题,因为我创建一个Facebook类似收件箱的评论系统。在'insertComment'方法中,我检查用户是否仍在评论之前没有任何其他用户评论,因此需要检查讨论是否需要更新。

诀窍是制作一个Meteor.Error,它可以停止所有事情并将错误响应发送给客户端,但是会收到'成功'消息。

Comments集合现在工作正常。从这个演变:

{ 
     "_id" : "GEtzmDPzDB4Yt2ux5", 
     "createdAt" : ISODate("2016-01-20T22:48:56.488Z"), 
     "userId" : "jza5u7SMoKwHMpJwi", 
     "projectId" : "on95SYYSjAy5p88Q4", 
     "content" : [ 
      "1er comentario hecho por netpoe", 
      "2do comment de netpoe", 
      "2do comment de netpoe", 
      "4to comment seguido de netpoe", 
      "4to comment seguido de netpoe", 
      "5to comment de netpoe", 
      "5to comment de netpoe", 
      "Ya no insertes más a netpoe", 
      "Ya no insertes más a netpoe", 
      "Ya no insertes más a netpoe", 
      "Ya no insertes más a netpoe" 
     ] 
    } 

对此

{ 
    "_id" : "7qeRrfTTT5JdTHdL3", 
    "createdAt" : ISODate("2016-01-21T18:33:35.435Z"), 
    "userId" : "D3mK7EKSKcvQ9v9bd", 
    "projectId" : "joZnWP3CZqwZFhD2C", 
    "content" : [ 
     "Gracias! La neta es que sí me tomó unas cuantas horitas", 
     "Pero ya está lista! :D" 
    ] 
}, 
{ 
    "_id" : "PBF8RfGFeZrx4y4ZD", 
    "createdAt" : ISODate("2016-01-21T18:33:50.790Z"), 
    "userId" : "jza5u7SMoKwHMpJwi", 
    "projectId" : "joZnWP3CZqwZFhD2C", 
    "content" : [ 
     "Nice! Pues a estrenarla no?" 
    ] 
}