0

I am working on a meteor project but having trouble with the asynchronous functionality. I would like to be able to reliably display information through a mongo collection find query that occurs on the server. The query should be located in a meteor method on the server, callable by the client. However, due to the asynchronous nature of meteor, the Template Helper returns undefined before the method call finishes. How can I reliably wait or restructure the code (trigger an event to display the information coming back from the query)?

What I want the html page to look like after loading:

<head>
    <title>appMongoTest</title>
</head>
<body>
    <h3>appMongoTest</h3>
    hello world<br />
    blah blah blah<br />
    more example test<br />
</body>

html file: appMongoTest/client/appMongoTest.html

<!-- appMongoTest.html -->

<head>
    <title>appMongoTest</title>
</head>
<body>
    <h3>appMongoTest</h3>
    {{> example}}
</body>

<template name='example'>
    <!-- DEBUG
    {{testString}}<br />
    {{#each testArray}}
        {{text}}<br />
    {{/each}}
    END DEBUG -->
    {{#each getResults}}
        {{content}}<br />
    {{/each}}
</template>

client js: appMongoTest/client/client.js

// client.js

// results() doesn't need to be seperated from the helpers
// seperated for clarity while debugging
function results() {
    /* Should I be using Meteor.apply instead with the
    onResultReceived or wait option? If so, how do I use that?
    I have been unable to figure out the syntax for the
    onResultReceived or wait options. */
    Meteor.call('findText', function(error, result) {
        if (error) { console.log(error); }
        else {
            // DEBUG console.log(result);
            // results is correctly getting the objects
            return result;
        }
    });
}

Template.example.helpers({
    testString: 'testString working',
    testArray: [
        { text: 'one' },
        { text: 'two' },
        { text: 'three' }
    ],
    getResults: function() {
        var res = results();
        // DEBUG console.log('what results() returns');
        // DEBUG console.log(res);
        // I am getting back undefined rather than the objects
        return res;
    }
});

server js: appMongoTest/server/server.js

// server.js

function addExample(name, type, content) {
    exampleCollection.update(
        { name: name },
        { $set: {
            type: type,
            content: content
        } },
        { upsert: true }
    );
}

Meteor.startup(function() {
    // DEBUG console.log('Hello Server!');
    exampleCollection = new Meteor.Collection('example');
    addExample('text0', 'text', 'hello world');
    addExample('text1', 'text', 'blah blah blah');
    addExample('text2', 'text', 'more example text');
});

Meteor.methods({
    'findText': function() {
        // DEBUG console.log('findingText');
        var results = exampleCollection.find(
            { type: 'text' },
            { fields: { content: true } }
        ).fetch();
        // DEBUG console.log(results);
        // DEBUG console.log(results[0].content);
        return results;
    }
})
David C
  • 1,898
  • 2
  • 16
  • 31
  • 1
    Why are you using a method at all and not just using the normal pub / sub functionality in Meteor? – pstuart2 Mar 08 '15 at 04:39
  • I am new to Meteor and wasn't aware of Meteor's publish/subscribe concepts. That is the type of functionality that I am looking for, thank you! – David C Mar 09 '15 at 17:18

1 Answers1

0

This is a ccommon problem in Meteor. You should use some defensive coding, I.e.

if(results) return results;

and in your template

{{#if results}}
  ...
{{else}}
  Loading
{{/if}}

This should stop your browser from throwing errors, and give feedback to the user if needed.

Sander van den Akker
  • 1,545
  • 11
  • 13