Pembantu meteor dipanggil beberapa kali dengan satu variabel templat

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

Templat:

<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>

Dan keluaran konsol saat halaman dimuat:

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

Jadi fungsi pembantu diaktifkan 10 kali saat memuat halaman (jumlahnya bervariasi). Adakah yang bisa menjelaskan apa yang terjadi di sini? Saya tidak dapat menemukan referensi apa pun untuk ini, terima dalam situasi di mana helper dipanggil dari beberapa {{ }} pada template. Juga ada cara untuk menghentikannya? Akhirnya saya perlu memproses tweet sekaligus sebelum dirender.


person kendlete    schedule 13.11.2014    source sumber


Jawaban (1)


Saat Anda melakukan pencarian, meteor mencatat ketergantungan untuk pembantu templat tersebut pada koleksi tempat Anda menemukan. Karena ketergantungan itu meteor akan memanggil template helper untuk setiap modifikasi koleksi.

Jika Anda belum berlangganan, tidak ada data yang dimuat di salinan sisi klien dari koleksi mongo Anda. Hanya ketika Anda menelepon berlangganan, meteor akan mulai menarik data dari server.

Jadi metode ini dipanggil beberapa kali karena pelanggan terus memasukkan dokumen baru ke dalam salinan lokal koleksi mongo Anda, memicu panggilan baru ke pembantu templat.

Pola terbaik untuk mengatasi masalah apa pun yang mungkin terjadi adalah dengan berlangganan helper dan menggunakan metode siap pakai di dokumentasi. Ready juga bersifat reaktif sehingga ketika semua data ditarik, ready akan diubah menjadi true dan helper akan dipanggil kembali.

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

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

Templat itu sendiri:

{{#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
Ok terima kasih. Saya berasumsi seperti ini. Apakah ada cara untuk menghentikannya melakukan hal ini? (dengan asumsi koleksi di server tidak berubah, seperti yang terjadi di sini). Tampaknya aneh jika sinkronisasi antara server tetap dan koleksi klien berjalan secara tidak sinkron. - person kendlete; 14.11.2014
comment
@kendlete memperbarui jawaban saya dengan contoh tentang cara bekerja dengan perilaku sistem berlangganan meteor - person Marco de Jongh; 14.11.2014
comment
Meteor.subscribe() juga memiliki panggilan balik yang sudah siap di dokumen, yang dapat digunakan untuk menunda memasukkan lebih banyak kode hingga langganan siap. Itu berbeda dengan .ready() yang mengembalikan boolean jika langganan sudah siap. Mungkin sedikit lebih rumit daripada pendekatan Marco. - person Paul; 14.11.2014
comment
Terima kasih keduanya sangat bermanfaat. Saya juga akan memasukkan if (ready) ke dalam helper untuk menghindari pemrosesan tweet sebelum langganan disinkronkan (tweet akan dikelompokkan sebelum dirender). - person kendlete; 14.11.2014