Struggling to load json from file (myData.json) on URL into an object so I can access property values.
-- The data loads immediately, I need it a lot in the app.
-- I'm going to access the data throughout the app, not just as part of one function that happens immediately after the data loads.
-- I've ensured the data in my file is properly formatted json.
Following the example on the jquery API, shouldn't I be able to do something simple like:
alert(jqxhr.myProperty);
and get the value? What step am I missing here? I've tried running eval and a variety of things like
var myObj=JSON.parse(jqxhr);
to no avail.
Please....thank you.
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.getJSON("example.json", function() {
alert("success");
})
.success(function() { alert("second success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
// perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function(){ alert("second complete"); });
I think you are making it too complicated :)
var JSON;
$.getJSON('example.json', function(response){
JSON = response;
alert(JSON.property);
})
//feel free to use chained handlers, or even make custom events out of them!
.success(function() { alert("second success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
the getJSON function automatically converts your response into a proper JSON object. No need to parse.
You mentioned that you are using this data all over the place, so you will have to wait for the ajax call to complete before the data is accesible. That means either wrapping your entire application in the getJSON callback. Or using a custom event to determine like so:
var JSON;
$(window).on('JSONready', function(){
alert(JSON.property);
});
$.getJSON('example.json', function(response){
JSON = response;
$(window).trigger('JSONready');
});
$('#elem').on('click', function(){
//event likely to take place after ajax call has transpired
//it would still be better to assign this listener in a callback,
//but you can get away with not doing it, if you put in a catch
if(JSON){
alert(JSON.property);
}
});
EDIT
After a quick live debug, the real reason for the data being unavailable was this: javascript that consumes JSON was located in a file include the page document NORTH of inline javascript performing the call. As a result JSON was not a global variable, and scope prevented its usage. If you truly need a variable to be global so it can be used with inline JS as well as any and all included js files, you may do so like this:
(function(){
var limitedScopeVariable = 25;
window.globalScopeVariable = 30;
})();
$(function(){
alert(globalScopeVariable); //works!
alert(limitedScopeVariable); //fails!
});
EDIT 2
As of jQuery 3.0, callback functions are different: The
jqXHR.success(), jqXHR.error(), and jqXHR.complete() callback methods
are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(),
and jqXHR.always() instead
from the comments #mario-lurig
the json data is passed to the callback function of $.getJSON.
So this would work:
var jqxhr;
$.getJSON("example.json", function(data) {
jqxhr = data;
});
// alert(jqxhr.property);
// caution: this won't work immediately on load, since the ajax call runs asynchronously and hasn't finished at that time
// it should be available at a later time, like a click event
$('a#something').click(function(){
if(jqxhr){
alert(jqxhr.property);
}else{
alert('getJSON not yet complete or failed');
}
});
I think this would be what you are looking for, you are trying to access the data returned from your call not the caller object itself. In your example, jqxhr is the object that handles the JSON call not the data. So,
$.getJSON("example.json", function(data) {
yourDATA = data;
})
//Use your data here
alert(yourDATA.aProperty);
The very first example on this page is similar to what I explained.
Related
So I've got some code that retrieves a series of objects from an API. When I try to store them in a global variable, it doesn't seem to do anything. Here's the code:
var current_corpus = {};
function page_init() {
$.getJSON("http://resource1.com", function(data) {
populate_collections(data);
populate_citations(data);
});
}
function populate_collections(collections) {
$.each(collections, function (i, item) {
current_corpus[item] = [];
});
}
function populate_citations(collections) {
$.each(collections, function (index, collection) {
$.getJSON("http://resource2.com/" + collection.collection_id, function(data) {
current_corpus[collection] = data;
console.log(current_corpus);
});
});
}
When this finishes, current_corpus is completely empty. Logging these items verifies that they're being returned from the resources I'm posting to. I think there's just something about the asynchronous nature of these calls that I'm missing.
The line
current_corpus[item] = [];
is superfluous I think as the line
current_corpus[collection] = data;
should do the same thing while also tying data to the key object. Either way at the end of these functions running trying to access current_corpus via the console just gives me back an empty object.
Resources for dealing with AJAX stuff like this would be appreciated as well.
It all depends on what you want to do when the ajax requests complete. The A in ajax stands for Asynchronous meaning that such requests are non-blocking -- i.e. they will run in the background as control moves to the next line. Which explains why you're seeing an empty object right after the functions that invoke the ajax requests.
You can confirm that your code is working fine or you can do something once all the requests complete by using the following code snippet:
$(function() {
$(document).on('ajaxStop', function() {
console.log( current_corpus );
//do something with the now fully constructed object
});
});
I am forced to use data from within the getJSON callback function outside of that function. Have a look:
$('#stars').raty({
score: function() {
var $value = 0;
var $id = <?=$id?>;
$.getJSON("getuserrating.php?id=" + $id, function(data) {
$.each(data, function(key, val) {
$value = val;
});
});
return $value;
},
});
This is what I tried but it failed, the $value is still set to 0, although inside the callback it's definitely set to an actual value. I know why it fails, because the AJAX request is send asynchronously. The problem is, the correct way, doing everything inside the callback, is not possible. As you can see I need to retrieve the JSON object within the raty (a plugin) setup. I would just use $.ajax() and set that to synchronous but the documentation marks this as deprecated for 1.8. I'd rather not introduce a solution that I know will be deprecated in the future.
Is there any way at all to do this? Maybe I just don't see the forest for the trees and there's an easy solution right before me. Thanks in advance :)
Approach is backwards if you need to use ajax to get the score.
Make the ajax call first, then pass the value to score within the ajax success
$.getJSON("getuserrating.php?id=" + $id, function(data) {
/* pseudo code here since I don't know the plugin and it's data requirments*/
var score= data.score;
$('#stars').raty({
score: score
});
});
EDIT: you can still pass the data into a score function this way also
Maybe this (taken from jquery getJSON api doc http://api.jquery.com/jQuery.getJSON/) could work:
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.getJSON("example.json", function() {
alert("success");
})
.success(function() { alert("second success"); })
.error(function() { alert("error"); })
.complete(function() { alert("complete"); });
// perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function(){ alert("second complete"); });
Just assign another raty attribute instead of returning.
I try to manipulate a variable inside a function. But it seems to forget the values once I exit the function, eventhough the variable is declared outside the function.
The essential code:
var posts = {};
// Perform a data request
// skjutsgruppens-page
$.oajax({
url: "https://graph.facebook.com/197214710347172/feed?limit=500",
*SNIP*
success: function(data) {
$.extend(posts, data);
}
});
// Gruppen
$.oajax({
url: "https://graph.facebook.com/2388163605/feed?limit=500",
*snip*
success: function(data) {
$.extend(posts, data);
}
});
The oajax retrievies data from facebook. I want to make a variable that contains the data from both oajax methods.
The actual code: http://eco.nolgren.se/demo/resihop/#
The issue is likely that the success function executes at an arbitrary time in the future--unless you specifically access posts after you know the success function has executed, you will receive undefined results, completely dependent on function and access timing.
The best approach is to handle this correctly by doing necessary work inside in the success function, or use something like jQuery's .when function.
I have the following code which is included in a keypress function:
$.getJSON('dimensions.json', function(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
});
I'm trying to first get the JSON string, save it in a variable and then run the each(). I want to basically separate the each() to be unlinked to the getJSON() function because I don't want it to fetch the json file for every keypress.
I've tried this, but it didn't work:
var JSONstr = $.getJSON('dimensions.json');
$.each(JSONstr, function(index) {
$('#div1').append(index);
});
In your first example, you do $.each in the callback. The callback is executed by some other callback after there result is received, while $.getJSON returns immediately without waiting for the result (since there is no blocking in JavaScript by design).
Therefore the code in your second example can never work: the $.each begins before any result is received from the web server, probably even before the request is sent. Whatever the return value of $.getJSON is, it can't, by the design of JavaScript, be the result of AJAX request.
UPD: Saw your comment, now I understand what you wanted to do. Here's a simple example of how to do this:
function ActualHandler(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
function KeypressHandler() {
if (window.my_data) { // If we have the data saved, work with it
ActualHandler(window.my_data);
}
else { // Otherwise, send the request, wait for the answer, then do something
$.getJSON('dimensions.json', function(data) {
window.my_data = data; // Save the data
ActualHandler(data); // And *then* work on it
});
}
}
Here, the ActualHandler is not launched before the data is received, and once that happens, all subsequent clicks will be handled immediately.
The downside in this particular case is that if user clicks again while the first request is running, one more will be sent. But to fix that you would need to maintain some queue, which is kind of out of scope here.
You fell into the asynchronous trap. Your $.each() function doesn't wait for your $.getJSON() call to get the data. You can get around this by using the good 'ol $.ajax() function. Like this:
function processJSON(data) {
$.each(data, function(index) {
$('#div1').append(index);
});
}
$.ajax({
url: 'dimensions.json',
dataType: 'json',
async: false,
success: processJSON(data)
});
Is jQuery able to read JSON data from X-JSON HTTP headers returned by the server? I've been searching through the jQuery docs, but all the examples I can find use JSON returned in the request body rather than the headers.
Yes, you need to call the getResponseHeader method of the XMLHttpRequest object, and do the JSON de-serialization manually:
function getHeaderJSON(xhr) {
var json;
try { json = xhr.getResponseHeader('X-Json') }
catch(e) {}
if (json) {
var data = eval('(' + json + ')'); // or JSON.parse or whatever you like
return data
}
}
Note that the try/catch is for some versions of Firefox where if the header is not present an error is thrown. I can't remember which version(s) were affected.
You have a couple ways to get a reference to the XMLHttpRequest object in jQuery:
hook into the complete callback of the ajax request, as opposed to the expected success callback (jQuery is kind of inconsistent wrt to what args are passed in what order to what callback function or global ajax trigger):
$.ajax({
// ...
complete: function(xhr) {
var data = getHeaderJSON(xhr);
// do with data as you wish
}
})
Alternatively you can save a reference to the XMLHttpRequest object returned to you from calls to .ajax/.get/.post etc, via a Closure. This allows you to use it inside whatever callback you choose (ie success or complete, or error for that matter):
var xhr = $.ajax({
// ...
success: function() {
var data = getHeaderJSON(xhr); // access xhr var via closure
// do with data as you wish
}
});
So to answer your title directly: no, jQUery obviously doesn't support this OOTB.
as of 1.4 jQuery's success: callback receives XMLHttpRequest -- (data,textStatus,XMLHttpRequest). So you don't have to use the complete: callback anymore, as laid out above.
Wish I could reply to the previous answer instead of adding a new answer.