I'm working on an Angular App, which loads data from an API.
Everything is working as expected, except periodic receiving this bug in Chrome console.log
TypeError: Cannot read property 'longitude' of undefined
This causes some of the subsequent functions to disfunction aswell. The line angular complains at, is the following
function updateMapWaypoint(lastposition) {
console.log("updateMapWaypoint(%s) called", lastposition);
console.log($scope.units[$scope.selectedUnitIndex]);
var longitude = (lastposition) ? $scope.units[$scope.selectedUnitIndex].lastposition.gps.longitude : $scope.unsortedPositions[$scope.selectedPositionIndex].gps.longitude;
Where to two first is debugging and the last one, the line causing trouble. As far as I can see from the printet object in the console. Javascript should have no trouble locating longitude from the object, however it throws the error and I can't find any way to solve it.
All help is appreciated and if more details is required, I'll provide if possible for me.
This looks like it might be a race condition.
console.log() will show you the object as it is right now, and not what is was when you called console.log(). To see the properties of an object at a certian point in time you must copy its content and send them to console.log(), for example by stringifying it:
console.log(JSON.stringify(myObject))
Or if you are using Angular:
console.log(angular.extend({}, myObject));
This is confusing (it has messed with me several times). Remember that you are sending console.log() an object reference, not a copy of the object.
Related
I'm baffled about why I'm getting an error when trying to access an array inside of an object in ReactJS.
I am using Redux to store an object in State.
I have a success function that allows the page to render, so by the time I get to this object it has for sure loaded. (I noticed a ton of similar questions to this where that's usually the problem).
When I do this I get the proper results:
const { events } = this.props
console.log(JSON.stringify(events.listSignup))
{"data":[{"eventID":"264712106049274377","name":"BookOne","email":null,"verify":null,"privacy":null,"order":null,"group":null},{"eventID":"264712106049274377","name":"BookTwo","email":null,"verify":null,"privacy":null,"order":null,"group":null}]}
I can see that the array "data" exists, but when I try:
console.log(JSON.stringify(events.listSignup.data[0].name))
or
console.log(JSON.stringify(events.listSignup.data[0]))
I get "TypeError: Cannot read property 'data' of undefined"
I'm at my wits end trying to figure out what's going on. Any advice would be much appreciated!
You're right to be baffled, because what you [think you] have observed isn't possible.
This happens a lot to me as a developer, and my advice is that when this happens, trust your knowledge (you know this isn't possible!) and double check what you are seeing.
I suspect that the first time your component renders, this.props.events is undefined, but then it very quickly re-renders with this.props.events being set.
I would suggest adding back this line (without the others):
console.log(JSON.stringify(events.listSignup))
And scrolling up in your javascript console to see if you have any logs that are just displaying undefined. If so, you probably need to double check the logic which is preventing the page from rendering before you have successfully received the data, as I suspect that is where your problem is.
I am currently reading Async Javascript by Trevor Burnham. This has been a great book so far.
He talks about this snippet and console.log being 'async' in the Safari and Chrome console. Unfortunately I can't replicate this. Here is the code:
var obj = {};
console.log(obj);
obj.foo = 'bar';
// my outcome: Object{}; 'bar';
// The book outcome: {foo:bar};
If this was async, I would anticipate the outcome to be the books outcome. console.log() is put in the event queue until all code is executed, then it is ran and it would have the bar property.
It appears though it is running synchronously.
Am I running this code wrong? Is console.log actually async?
console.log is not standardized, so the behavior is rather undefined, and can be changed easily from release to release of the developer tools. Your book is likely to be outdated, as might my answer soon.
To our code, it does not make any difference whether console.log is async or not, it does not provide any kind of callback or so; and the values you pass are always referenced and computed at the time you call the function.
We don't really know what happens then (OK, we could, since Firebug, Chrome Devtools and Opera Dragonfly are all open source). The console will need to store the logged values somewhere, and it will display them on the screen. The rendering will happen asynchronously for sure (being throttled to rate-limit updates), as will future interactions with the logged objects in the console (like expanding object properties).
So the console might either clone (serialize) the mutable objects that you did log, or it will store references to them. The first one doesn't work well with deep/large objects. Also, at least the initial rendering in the console will probably show the "current" state of the object, i.e. the one when it got logged - in your example you see Object {}.
However, when you expand the object to inspect its properties further, it is likely that the console will have only stored a reference to your object and its properties, and displaying them now will then show their current (already mutated) state. If you click on the +, you should be able to see the bar property in your example.
Here's a screenshot that was posted in the bug report to explain their "fix":
So, some values might be referenced long after they have been logged, and the evaluation of these is rather lazy ("when needed"). The most famous example of this discrepancy is handled in the question Is Chrome's JavaScript console lazy about evaluating arrays?
A workaround is to make sure to log serialized snapshots of your objects always, e.g. by doing console.log(JSON.stringify(obj)). This will work for non-circular and rather small objects only, though. See also How can I change the default behavior of console.log in Safari?.
The better solution is to use breakpoints for debugging, where the execution completely stops and you can inspect the current values at each point. Use logging only with serialisable and immutable data.
This isn't really an answer to the question, but it might be handy to someone who stumbled on this post, and it was too long to put in a comment:
window.console.logSync = (...args) => {
try {
args = args.map((arg) => JSON.parse(JSON.stringify(arg)));
console.log(...args);
} catch (error) {
console.log('Error trying to console.logSync()', ...args);
}
};
This creates a pseudo-synchronous version of console.log, but with the same caveats as mentioned in the accepted answer.
Since it seems like, at the moment, most browsers' console.log's are asynchronous in some manner, you may want to use a function like this in certain scenarios.
When using console.log:
a = {}; a.a=1;console.log(a);a.b=function(){};
// without b
a = {}; a.a=1;a.a1=1;a.a2=1;a.a3=1;a.a4=1;a.a5=1;a.a6=1;a.a7=1;a.a8=1;console.log(a);a.b=function(){};
// with b, maybe
a = {}; a.a=function(){};console.log(a);a.b=function(){};
// with b
in the first situation the object is simple enough, so console can 'stringify' it then present to you; but in the other situations, a is too 'complicated' to 'stringify' so console will show you the in memory object instead, and yes, when you look at it b has already be attached to a.
This problem is honestly the strangest thing I have encountered. I have no idea whether or not it's able to be reproduced, so I'm just asking for some input on possible causes.
The code is accessing a property (transit) on an object inside a lodash 'each' loop. The object is called step.
The code throws an exception when it tries to access a property on transit, on step (step.transit.propName). It says 'transit' is undefined.
But when you type 'step.transit' into the console, somehow the debugging tools are able to access it!
The code, and the V8 inspector tools, somehow aren't looking at the same thing. What on earth is happening here?
You'll have to look at the screenshot there to really grasp what's going on. Notice how the watch expressions show step['transit'] being both available, and unavailable at the same time....
It's strange, when I stop the code at that line, and type 'step.transit' into the console, I get the appropriate object. But there's some crazy thing in the code, where it can't seem to execute it.
This is an AngularJS app. Is there any way I could have screwed this data up in order to cause this weird error?
We have a campus map which has been created by a number of our students. For the most part, it runs fine, but there is one persistent error which we are unable to clear. There is a sidebar which lists out the buildings and points of interests which are represented on the map which, when clicked, [simulate a click][1] on the polygon for the building/poi.
function sideClick(poly) {
google.maps.event.trigger(buildingpoi[poly],'click');
};
Where buildingpoi[i] is an array which holds the information regarding each polygon.
Whenever a click is triggered, it refers to a method called shapeClick() which handles the display of information and repositioning of the map to center on the building/poi. Regardless of whether it is the polygon itself or the link in the sidebar, this method executes completely without error.
However, when the sideClick() function is used, or when the click trigger is called in the code, an error occurs in the Google API files, namely a main.js file:
TypeError: b is undefined
...(a.Va)||b.set("poly",null)})]};function VH(a){var b=a.Se;b.b||(Q(Xe,function(c){...
This error appears to occur after the successful execution of the shapeClick() method, suggesting that the error lies- as noted in the error message- in the GMaps API main.js file at some point after shapeClick() is called. Generally, this does not cause an issue on the front end, but when I attempted to include another method which calls sideClick(), any code I place after sideClick() is not executed due to the error.
I've attempted a number of my own tests/fixes, but the best I've been able to do is narrow down where the error is triggered. My searches also appear to come up with related yet dissimilar results. I assume the answer may be very simple, but for me it has been elusive.
Map: https://www.beloit.edu/maps/
Although you did not access the event-argument in shapeClick(what will not be supplied when you trigger the event), it seems that the API internally tries to access this argument.
The API tries to read the vertex-property(don't ask me why) of the PolyMouseEvent(that's what event is expected to be).
Accessing a property of an undefined object results in an error, that's what the message says.
Provide an empty object as argument when you trigger the event:
google.maps.event.trigger(buildingpoi[poly], 'click',{});
...and the error will go away(accessing an undefined property of an existing object is not an error)
Is buildingpoi[i] as you said an array holding information for the polygons? or a reference to the polygon itself?
This function needs the reference to the actual polygon, which is fine if it's in an array.
I'm trying to debug the popular "cannot call method 'addClass' of undefined" of jQuery slider in range mode, and finding some strange things. Some people say this error is due to values being passed in as strings instead of integers, but my values are verified integers and I'm out of ideas, so I went to try and debug jQuery UI, hitting a dead end instantly.
See image:
As you can see, when I expand the options object in the dev tools, options.values is an array of two NaNs. However, if I console.log(options.values) I get the real array, as it should be, with proper numeric values. What's worse, when I log them directly with console.log(options.values[0]) for example, I get the proper value.
However, when slider requests the values, it always gets NaN back - this is apparent when calculating the closestHandle for the range slider - the NaN is so toxic it poisons the entire loop and returns an undefined closestHandle, thus causing the aforementioned "addClass" error.
Why does the situation from the image happen? Why can it happen? Apparently two identical properties contain different values depending on the way of accessing them.
The Chrome console is a bit tricky. The state of the Object you see in does not necessarily reflect the state at the time it was logged. It can be an 'updated' view.
While this does not solve your main problem it's obvious that logging an object doesn't help you much with debugging on Chrome in many situations. A breakpoint would be a better choice.
That said, somewhere in your code the object seems to be changed.