ziomyslaw
ziomyslaw

Reputation: 211

Unexpected additional funtion calls in Meteor

Here is a template to demonstrate the issue. The randomArtist is a function that return a document from mongodb. I call the function 3 times, each time I use a different field from that document.

<template name="featuredArtist">
    <p>{{randomArtist.artistName}}</p>
    <p>{{randomArtist.description}}</p>
    <p>{{randomArtist.randId}}</p>
</template>

Here is a template logic. On the server start up I initialize the collection with some data, so there should be (I think) available for the View part from the beginning. On the client I get a random document, then store its id (randId) in session to skip lottery during next function call. (PS. It's not the key, but any improvement suggestions are welcome, I'm the beginner in Meteor.)

Artists = new Mongo.Collection("artists");

if (Meteor.isServer) {
    Meteor.startup(function () {
        Artists.insert({ randId: 0, artistName: "Artis Name 1", image: "url", description: "Description of Artis Name 1"});
        Artists.insert({ randId: 1, artistName: "Artis Name 2", image: "url", description: "Description of Artis Name 2" });
        Artists.insert({ randId: 2, artistName: "Artis Name 3", image: "url", description: "Description of Artis Name 3" });
        Artists.insert({ randId: 3, artistName: "Artis Name 4", image: "url", description: "Description of Artis Name 4" });
        Artists.insert({ randId: 4, artistName: "Artis Name 5", image: "url", description: "Description of Artis Name 5" });
    });
}
if (Meteor.isClient) {
    Meteor.subscribe("artists");

    Template.featuredArtist.helpers({
        randomArtist: function(){
            var randId = Session.get("artistRandId");
            if(!randId){
                var rand = (Artists.find().count() * Math.random()) | 0;
                var artist = Artists.findOne({randId:{$lte:rand}}, {sort: {randId: -1}});
                if (!artist) {
                    artist = Artists.findOne( { randId : { $gte : rand } } );
                }
                if (!artist) {
                    console.log('Mongo.Artists is empty');
                } 
                else {
                    console.log(artist);
                    Session.set("artistRandId", artist.randId);
                    return artist;
                }
            }
            else {
                console.log('randId='+randId);
                return Artists.findOne( { randId: randId } );
            }            
        }
    });
}

Working demo is on http://meteorpad.com/pad/MhwXS6MpXQoTYh4Lw/Artists

What I observe in logs is that the 'randomArtist' function is call 7(!) times instead of expected 3 times as it is invoked in the template:

Can any explain me where are these additional calls come from? In my real application I can observe more number of calls - probably because I use more complicated templates, does mean that the featureArtist is embedded inside another ones.

It is also unclear how is it possible that in logs I see that the collection is empty as it seems to be populated at start up?

Upvotes: 0

Views: 54

Answers (1)

Peppe L-G
Peppe L-G

Reputation: 8345

I can't say why your helper is called exactly 7 times, but you can probably get rid of it by using the #with block helper like this:

<template name="featuredArtist">
    {{#with randomArtist}}
        <p>{{artistName}}</p>
        <p>{{description}}</p>
        <p>{{randId}}</p>
    {{else}}
        <p>Got no random artist :(</p>
    {{/with}}
</template>

and remove the artistRandId session from your helper. Your helper will probably get called 2 times now, since the template will probably be rendered before the client receives the artist from the artist subscription (the second times occur when the client has received the artists).

Upvotes: 1

Related Questions