Firebug's console.log: debugging asynchronous variables - javascript

I am trying to debug some javascript code. The variable I want to debug is a JS object of objects, loaded asynchronously (ajax callback). I am debugging it outside the callback.
I am pretty sure that the problem is a race-condition problem, but I want to be sure (and it is not my question).
The problem I find when debugging is that console.log gives me an information which does not make sense with what the code is doing. Therefore, either I am missing something in the code, or the result I see in the console is the not a snapshot of the state of the variable when I runned console.log.
If it turns out to be the later, how can i get a snapshot of the state of an asynchronously loaded JS object?
This is a simplified example of the code:
//This call takes a while to invoke the callback
$.get("url",function(data){
//Process data
globalVariable = data; //JSON (Object of objects)
}
//Couple lines afterwards
/* This console.log shows (in Firebug's console) "Object { }" and when I click it,
I can see the object with all its fields filled (oher objects)
*/
console.log(globalVariable);
for(var e in globalVariable){
//Does not enter here, meaning that the object is empty
}

console.log is itself asynchronous and it shows references rather than snapshots, sometimes.
If you log an object you will get a nice clickable interface where you can inspect the object. If the object changes you will see those changes reflected there.
If you want a real snapshot you're going to have to do some serialization and serializing objects is not trivial. If your objects just are data and have no functions or references you can use JSON.stringify(obj, undefined "\t").
A smarter way is to pause your asynchronous events so you can inspect the latest state of the object.

Write it like this instead. This way globalVariable will have the data before you act upon it.
$.get("url",function(data){
//Process data
globalVariable = data; //JSON (Object of objects)
for(var e in globalVariable){
//this will run
}
}

Related

Why is this data showing undefined when there are clearly values?

On my page, I'm logging this:
console.log(self);
console.log(self.data.events);
The self is showing data, however self.data.events is showing undefined, how am I referencing this wrong?
but why is console.log(self.data) working but not console.log(self.data.events)?
As #Nick Parsons hinted in his comment, it might be because console.log behaves asynchronously in some browsers and will not log a "snapshot" at the time it was logged but will reflect updates on whatever is referenced, in this case self.data (which is initially defined as an empty object!)...
I have a feeling that #Dinesh Kumar's comment is on the right track, you're calling these functions after each other:
self.load_event_data();
self.load_zip_codes();
self.bind_events();
self.handle_filter_params();
self.cluster();
the issue is within self.cluster() but it is possible that the AJAX call you're making in self.load_event_data() is not be done yet when self.cluster() is called, so I'd suggest you try and call self.cluster() from within self.load_event_data() whenever you got data updated with the events.

how to access json object after loading it in d3

I loaded a json object using d3.json and assigning the loaded json file to a global variable but when I print the global variable to the console it returns undefined, but when i type in the global variable in the chrome console it returns what I need it to. Essentially, I am just looking to load the json object be able to use it outside the d3.json function. This seems like a relatively simple task but I am a js/d3 newby so any help is greatly appreciated!
Thanks!
Code is provided below
<script type = "text/javascript" source='https://d3js.org/d3.v4.min.js'>
var gapminder;
d3.json("D3_jsondata.json", function(data){
gapminder = data;
});
//above prints in console when i type in gapminder
console.log(gapminder);//prints as 'undefined' in Chrome's console
</script>
Calling .json() gets you a promise for the body of the http response that is yet to be loaded. Try to start rendering inside the callback of the json!
For d3.json, d3.csv and d3.tsv are asynchronous request functions, so the console.log() will run before d3.json() where "gapminder" is still undefined.
After the console.log() then it's the term of d3.json() to run and you make a assignment "gapminder" with the json data, so it's not undefined anymore.

Script not printing error in JavaScript Chrome console

I have just spent far too long trying to find a problem with the code below.
In turned out that because of the context that addRoute was called in, keys() was not returning the keys of the results object. To fix this I had to use Object.keys() despite it working without a problem in the JavaScript console (which I later realised was because of the context).
My question is, why didn't this show in my JavaScript console? It took me quite a while to realise (I have cropped the full code, the actual function is a lot bigger).
Wrong, but no error in the console:
Map.prototype.addRoute = function (results) {
var sectionsIDs = keys(results);
}
Correct
Map.prototype.addRoute = function (results) {
var sectionsIDs = Object.keys(results);
}
Your first function uses the keys console API function.
That "Command Line API Reference" page includes the warning:
Note: This API is only available from within the console itself. You cannot access the Command Line API from scripts on the page.
Thus, it is by design that the keys function only exists for code run directly on the console.
Chrome gives you a small hint about the keys function being a console-only function if you view it in the console:
> keys
function keys(object) { [Command Line API] }

Different behavior seen accessing value in stored variable vs function call that returns the variable

Apologies for what must be a total newbie question. I'm starting to play with Backbone talking to an existing Rails app. I'm using the Console in Chrome to test out some JS functions, and I'm seeing behavior that I cannot understand.
I've defined a JS function called apiGet which just wraps a jQuery AJAX call with some custom stuff jammed into the HTTP request header.
When I call apiGet and store the result in a variable, I can then call .responseText on that variable and see the contents of that field.
However, if I just try to call .responseText on the apiGet(...) call, i.e. apiGet(...).responseText the result displayed is undefined. This makes no sense to me :-)
I'm missing something obvious -- can someone clue me in?
Here's what the console looks like:
> var url = 'http://localhost:3002/api/exercises/11';
undefined
> result = apiGet(url);
Object {readyState: 1, getResponseHeader: function, getAllResponseHeaders: function, setRequestHeader: function, overrideMimeType: function…}
> result.responseText
"{"id":1,"number":2,"version":1,"markup":null,"html":null,"background":null}"
> apiGet(url).responseText
undefined
It looks like your function apiGet returns an xhr (request object). This will execute asynchronously, so that responseText isn't available until the response comes back from the server. When you call the property directly on the return, it happens so fast that the server hasn't responded yet, but when you use the console manually, by the time you type out result.responseText and press enter, the result is already in.
Just a guess of course, since I haven't seen the contents of getApi.

Unable to access attribute after fetch

I am testing some code in my web console (using coffescript)
#user = new Onethingaday.Models.User()
#user.url= "/users/#{current_user.get('nickname')}.json?id_type=nickname"
#user.fetch()
console.log(#user)
console.log(#user.get("facebook_id"))
The console.log(#user) line shows the following:
However, console.log(#user.get("facebook_id")) shows undefined.
I see that user has the facebook_id attribute. How do I retrieve the value of it?
This looks like a timing issue, albeit an odd one. fetch is asynchronous; you need to wait until its success callback is called before trying to access any attributes.
Try this:
#user.fetch success: =>
console.log(#user)
console.log(#user.get("facebook_id"))
It's confusing that the first console.log would show user.attributes.facebook_id existing and the second wouldn't, but console.log is itself asynchronous in Webkit's implementation, so what's going on is that the #user.get call is being resolved immediately (synchronously), whereas the object inspection in the first console.log is resolving later—after the fetch completed.
It looks like facebook_id is a property of the attributes property of the #user object. If that's the case, I'd think the following would work:
#user.attributes.facebook_id

Categories

Resources