2014-01-07 54 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?" 
    ] 
}