[solved] Collection find gives undefined. Unable to access fields from a collections


#21

@robfallows : Correct! My console will display jsonLoc but jsonLoc.lat gives undefined error … I’ve also tried every other form of access that I can think of i.e. jsonLoc.["lat"] , jsonLoc["lat"] … etc

An assumption on my part is that the lines of code beneath the findOne are synchronous (?).


#22

Everything there is synchronous - including (on the client) findOne.

However, findOne may return nothing if the published docs have not been sync’d from the server when it runs.

Is $ctrl... angular syntax? Are angular helpers the same a Blaze template helpers? In other words, do they re-run reactively?


#23

Yes it’s angular syntax. Yes it is reactive, which is the whole reason I set out on this adventure in the first place. So if a new row is inserted into locs with latest=1 then the webpage automatically updates the map (google static maps api). And that works. (the previous row that was latest is set to latest=0)


#24

What I would expect to happen (with Blaze) is that the helper first runs before the data is sync’d (the findOne is undefined). At some time later, when the data becomes available, the helper re-runs and the findOne returns a document. However, as soon as the findOne succeeds, the .lat property will be available. I cannot think of anything which would give you a document with a .lat property (console.log(jsonLoc);), but then not let you access that property (console.log(jsonLoc.lat);)


#25

Seems like your console.log(json) contains a complete javascript object. Are you confusing yourself by calling the object ‘json’ and json string ‘str’?

Start by checking if Locs.findOne({latest: “1”}) returns anything at all.
Another danger zone is that yo use “1” rather than 1 (string rather than number) are you consistent there? Mongo sure is…

Lastly: “latest” can easily be replaced by simply checking the timestamp, you don’t need to set & reset the latest parameter. Sort by timestamp desc


#26

@robfallows Yep. Basically where I’m at. My desire to understand why, has now overtaken my need to access the darned variable in the first place. fyi, I’m gonna string manipulate it out later to see that it is actually there. Before I go mad.


#27

@ralof Thx & yes my variable names are all over the place and very misleading. I will tidy all that up.
Yes Locs.findOne({latest: “1”}) returns data.
Take your point about 1 & “1”.
There’s a reason I use latest rather that order desc on date but adding that here might skew the topic.


#28

Errrm. Is it possible that Meteor syncs the console log?


#29

AFAIK, on the browser, console.log is always synchronous. It reports the values it sees at the time it’s invoked (there’s neither a callback option nor a returned Promise to allow waiting on an asynchronous operation). That means your console.logs will be executed in the order you’ve written them. Given that you have a valid object at the start, and you’re then console.logging what’s in it, it should work as you expect it to. There’s no asynchronicity needed or expected here.


#30

you have jsonLoc as a global variable? Something is changing it in between?


#31

Although we have to remember here that when he logs the object, it’s a reference and so while it may not contain the lat field when it is first logged to the console, when looking through the object with the dropdown, it will have the field once it has been assigned to the object.

This is a good explanation why he sees the field in the object but not when he logs the field itself.


#32

If he use findOne, the result will not mutate


#33

unfortunately I beg to differ…


#34

findOne is synchronous, so unless angular somehow pour a bucket of async in there, the return value from Coll.findOne() will be static unltil it is called again.

I think this is simple issue of cleaning up the code, use a debugger and step through


#35

Are you saying that findOne can complete, but with incomplete data? That goes against my understanding of “returns undefined”, then “returns complete document”. My expectation is that the helper always runs to completion before re-running on a reactive change, so:

// data not available
// runs the helper:
  console.log(doc); // undefined
  console.log(doc.x); // undefined
// helper runs to completion
// time passes ...
// data becomes available
// runs the helper:
  console.log(doc); // {a:1, b:2, ..., x:99}
  console.log(doc.x); // 99
// helper runs to completion

#36

It’s not a function of the code, it’s a function of chrome dev tools… Try this little experiment…

In the dev tools console type

let obj = {};

console.log(obj);

obj.lat = '1234';

don’t click the dropdown arrow next to the object in the console till after you have assigned the string to obj.lat or it won’t work the same. Once you try this you will see what I mean.


#37

For this reason if you log the direct return of a findOne and then click the dropdown after new data has come in, you’ll see the future data in the object even though it wasn’t there when you first logged the object to the console.


#38

https://bugs.webkit.org/show_bug.cgi?id=35801


#39

Yes, I’ve seen that behaviour before. It’s easy enough to dereference the object

console.log(JSON.parse(JSON.stringify(obj)));
console.log(JSON.parse(JSON.stringify(obj.lat)));

but I’d still expect a log showing

undefined
undefined
some object
some property

whereas what’s been reported sounds more like:

some object
undefined

#40

Agreed… I think we are going to need a reproduction to nail this down.