admin管理员组

文章数量:1391977

I am making a project with Meteor and I'm having some issues trying to get data out of mongodb in JavaScript. I have the following in a function:

console.log(Time.find({today: "Saturday"}).fetch());

In my publish.js file on the server side I have the following:

Meteor.publish("time", function () {
  var currentUserId = this.userId;
  return Time.find({user: currentUserId});
});

I am making a project with Meteor and I'm having some issues trying to get data out of mongodb in JavaScript. I have the following in a function:

console.log(Time.find({today: "Saturday"}).fetch());

In my publish.js file on the server side I have the following:

Meteor.publish("time", function () {
  var currentUserId = this.userId;
  return Time.find({user: currentUserId});
});

And In my subscriptions file I have the following:

Meteor.subscribe("time");

This function gets called later down in the code but it returns an empty array. If I run this code in my browsers console it returns an array with 2 objects in it, which is correct. This leads me wondering if I can use the .fetch() function from within my code? As if I leave off the .fetch() it returns what looks like the usual giant object. My real problem is I need the data in the form that .fetch() gives it to me in. I think it's because the function gets triggered before the data gets a chance to load in, as if I switch out the .fetch() for a .count() it returns 0.

Is there any way around this or a fix?

Share Improve this question edited Dec 6, 2015 at 10:29 Alaister Young asked Dec 5, 2015 at 12:59 Alaister YoungAlaister Young 3574 silver badges20 bronze badges 5
  • This is probably a pub/sub issue. Can you please show the exact context of this piece of code (where and when it is called) and what pub/sub strategy you use? – Kyll Commented Dec 5, 2015 at 14:08
  • The funny thing is insecure and autopublish are on already as I haven't got to the publish subscribe side of my app yet. – Alaister Young Commented Dec 5, 2015 at 22:32
  • This is exactly why I have asked you to provide more data as to how your logic is implemented. The likely root cause is that you are trying to access data before it had time to arrive. Please edit your question to include the exact context of your code. – Kyll Commented Dec 5, 2015 at 22:50
  • 1 .fetch() merely converts a cursor into an array of objects. The cursor object has many methods (functions) while the array is pure data. However even when data isn't yet available the cursor will look "giant" but it can't provide you with data. You can quickly check the length of a cursor with Time.find().count() for example. – Michel Floyd Commented Dec 6, 2015 at 0:46
  • @Kyll I have updated the code to include the extra information. @MichelFloyd I did the Time.find().count() and it returned 0? Is that because the page is loading faster than the data? If so is there a way to stop this happening? – Alaister Young Commented Dec 6, 2015 at 10:33
Add a ment  | 

1 Answer 1

Reset to default 6

Where are you you running that console.log?

There are a couple fundementals here that I believe you may have glossed over.

1 Pub / Sub

This is how we get data from the server, when we subscribe to a publication i bees active and begins to send data, this is neither instant or synchronous, (think of it more like turning on a hose pipe), so when you run your console.log, you may not yet have the data on the client.

2 Reactive contexts

One of the fundamental aspects to building anything in meteor is its reactivity. and it helps to start thinking in terms of reactive and non reactive contexts. A reactive context is one that re-runs each time the data it depends on changes. Using an autorun (Tracker.autorun or this.autorun insdie a template lifecycle callback) or a template helper are good examples. By placing it in a template helper it will re-run when the data is available.

Template.Whatever.helpers({
    items: function() {
        // ...do your find here.....
    }
});

As items is a reactive context, depending on the collection data, it re-run when that changes, giving you access to the data when the client has them.

3 Retrieving Non Reactive Data

Alternatively it is also possible to retrieve data non-reactively by using Meteor.call with a meteor method, and then doing something with the result, in the callback to the Meteor.call. Depending on what you're doing, Meteor.wrapAsync may also be your friend here.

a simple example (out of my head, untested) :

// on the server
Meteor.methods({
    gimmeStuff: function() {
        return "here is your stuff kind sir!";
    }
});

// on the client
Meteor.call('gimmeStuff', function(err, result) {
    if (err || !result) {
       console.log("there was an error or no result!");
       return false;
    }

    console.log(result);
    return result;
});

4 Its Unlikely that you actually need ithe .fetch()

  • If you're working with this in a template, you don't need a fetch.
  • If you want this to be non-reactive you don't need a fetch
  • As one of the menters mentioned, a cursor is just a wrapper around that array, giving you convenient methods, and reactivity.

5 Go Back to the Begining

If you haven't already, I would highly remend working through the tutorial on the meteor site carefully and thoroughly, as it covers all of the essentials you'll need to solve far more challenging problems than this, as well as, by way of example, teach you all of the fundamental mechanics to build great apps with Meteor.

本文标签: javascriptUsing the find()fetch() from within a function in MeteorStack Overflow