ตัวช่วยดาวตกถูกเรียกหลายครั้งด้วยตัวแปรเทมเพลตเดียว

Tweets = new Meteor.Collection('tweets');

if (Meteor.isClient) {

  Meteor.subscribe('tweets');

  Template.Panel.helpers({
    items: function() {
      var days_tweets = Tweets.find();
      console.log(days_tweets.count());
      return days_tweets;
    });
  }

if (Meteor.isServer) {
  Meteor.publish('tweets', function() {
    return Tweets.find({}, {limit: 1000});
  });

แม่แบบ:

<body>
<h1>This is a list of tweets</h1>
  {{> Panel}}
</body>

<template name="Panel">
<h2>A list of tweets sorted by size</h2>
    {{#each items}}
        <p>item</p>
    {{/each}}
</template>

และคอนโซลเอาต์พุตเมื่อโหลดเพจ:

Tweet count:  0
Tweet count:  129
Tweet count:  272
Tweet count:  366
Tweet count:  457
Tweet count:  547
Tweet count:  672
Tweet count:  814
Tweet count:  941
Tweet count:  1000

ดังนั้นฟังก์ชันตัวช่วยจะเริ่มทำงาน 10 ครั้งในการโหลดหน้าเว็บ (จำนวนครั้งจะแตกต่างกันไป) ใครช่วยอธิบายสิ่งที่เกิดขึ้นที่นี่ได้ไหม ฉันไม่พบการอ้างอิงถึงสิ่งนี้ ยอมรับในสถานการณ์ที่มีการเรียกตัวช่วยจากหลาย ๆ {{ }} บนเทมเพลต แล้วมีวิธีหยุดมันบ้างไหม? ในที่สุด ฉันก็ต้องประมวลผลทวีตในคราวเดียวก่อนจึงจะแสดงผลได้


person kendlete    schedule 13.11.2014    source แหล่งที่มา


คำตอบ (1)


เมื่อคุณทำการค้นหา meteor จะลงทะเบียนการขึ้นต่อกันของตัวช่วยเทมเพลตนั้นในคอลเลกชันที่คุณค้นพบ เนื่องจากการพึ่งพานั้น meteor จะเรียกตัวช่วยเทมเพลตสำหรับการแก้ไขคอลเลกชันทุกครั้ง

หากคุณยังไม่ได้สมัคร จะไม่มีการโหลดข้อมูลในสำเนาฝั่งไคลเอ็นต์ของคอลเลกชัน mongo ของคุณ เฉพาะเมื่อคุณโทรสมัครสมาชิกเท่านั้นที่ดาวตกจะเริ่มดึงข้อมูลจากเซิร์ฟเวอร์

ดังนั้นวิธีการนี้จึงถูกเรียกหลายครั้งเนื่องจากการสมัครสมาชิกจะแทรกเอกสารใหม่ลงในสำเนาคอลเลกชัน mongo ในเครื่องของคุณ ทำให้เกิดการเรียกใหม่ไปยังตัวช่วยเทมเพลต

รูปแบบที่ดีที่สุดในการแก้ปัญหาใดๆ ที่อาจเกิดขึ้นคือสมัครรับข้อมูลในตัวช่วยและใช้วิธีการพร้อมในการสมัครสมาชิก เอกสาร Ready ยังเป็นปฏิกิริยา ดังนั้นเมื่อข้อมูลทั้งหมดถูกดึงเข้ามา ready จะถูกเปลี่ยนเป็น true และผู้ช่วยเหลือจะถูกเรียกอีกครั้ง

  Template.Panel.helpers({
      items: function() {
          var ready = Meteor.subscribe('tweets').ready();
          var days_tweets = Tweets.find();

          return {
              data: days_tweets,
              ready: ready
          };
      });
  }

เทมเพลตเอง:

{{#with items}}
     {{#if ready}}
         {{#each data}}
             <p>item</p>
         {{/each}}
     {{else}}
         Show a spinner or whatever
     {{/if}}
{{/with}}
person Marco de Jongh    schedule 13.11.2014
comment
โอเคขอบคุณ. ฉันถือว่าบางอย่างเช่นนี้ มีวิธีใดที่จะหยุดการทำเช่นนี้หรือไม่? (สมมติว่าคอลเลกชันบนเซิร์ฟเวอร์ไม่มีการเปลี่ยนแปลง ซึ่งเป็นกรณีนี้) ดูเหมือนแปลกที่มีการซิงค์ระหว่างเซิร์ฟเวอร์คงที่และคอลเลกชั่นไคลเอนต์ที่ทำงานแบบอะซิงโครนัส - person kendlete; 14.11.2014
comment
@kendlete อัปเดตคำตอบของฉันพร้อมตัวอย่างเกี่ยวกับวิธีการทำงานกับพฤติกรรมของระบบสมัครสมาชิกของ meteor - person Marco de Jongh; 14.11.2014
comment
Meteor.subscribe() ยังมีการโทรกลับที่พร้อมใช้งานในเอกสาร ซึ่งสามารถใช้เพื่อชะลอการใส่โค้ดเพิ่มเติมจนกว่าการสมัครจะพร้อม นั่นแตกต่างจาก .ready() ซึ่งส่งคืนบูลีนหากการสมัครสมาชิกพร้อมแล้ว อาจจะยุ่งยากกว่าแนวทางของมาร์โกเล็กน้อย - person Paul; 14.11.2014
comment
ขอบคุณทั้งสองมีประโยชน์มาก ฉันจะใส่ if (ready) ไว้ในตัวช่วยเพื่อหลีกเลี่ยงการประมวลผลทวีตก่อนที่จะซิงค์การสมัครรับข้อมูล (พวกเขาจะได้รับคลัสเตอร์ก่อนที่จะแสดงผล) - person kendlete; 14.11.2014