I am sending the jsonp request as:
var jsoncallback = "?jsoncallback=?"
$.getJSON( reportURL + jsoncallback, {
tags: "",
tagmode: "any",
format: "json"
})
.done(function( data ) {
$.each( data.items, function( i, item ) {
alert( item );
});
});
I have put an alert to see if the request works. On server side, in node js file I am responding to request as:
..
console.log("request received");
response.writeHead( 200, { "Content-Type": "application/json" } );
..
response.end();
In the logs I can see that the request received. The problem is that no alert windows pops up.
What could be the reason to this?
I just reponse.writeHead(...) and (for testing reasons - just the head and end) response.end()
With the jsoncallback=? in the URL, jQuery is expecting a JSONP <script> as a response. For this to work, the server should at the very least write out the "padding."
That is a call to the function named by jsoncallback. And it won't be just ? -- jQuery replaces that with a pseudo-random function name along the lines of jQuery1910123456789_0123456789. For that, the response should at least be:
jQuery1910123456789_0123456789();
You'll need to get the value from the request.url:
var parsedUrl = url.parse(request.url, true);
var query = parsedUrl.query || {};
if ('jsoncallback' in query) {
response.write(query.jsoncallback + '();');
}
// ...
And, once you have data to output with it:
if ('jsoncallback' in query) {
response.write(query.jsoncallback + '(' + JSON.stringify(data) + ');');
} else {
response.write(JSON.stringify(data));
}
Have you confirmed the JSON is correctly formatted? Check it against http://jsonlint.com/.
From the getJSON() docs:
As of jQuery 1.4, if the JSON file contains a syntax error, the
request will usually fail silently.
Related
I was running some jQuery code when suddenly I saw through Firebug Console that when I force a 500 error, the code inside .fail() method, is not being fired:
$.ajax({
url: "someAction.do",
data: "param1=param¶m2=param",
dataType: "xml"
}).done(function(xml){
//some stuff with my data
}).fail(function(xml){
//some other different stuff with my data that is not being fired
});
In the other hand, in a Java Action, I set the HttpResponse Status to "500" when an error occurs, for example, POSTING an invalid field trough the Ajax call, like searching in a database for an email that is not present, and then show the error trough ajax:
<xml version=bla,bla...>
<item>
<name>message</name>
<value>Invalid input data</value>
</item>
</xml>.
Any ideas why? I just want to use the new methods fail() and done(). I know I could do this using the statusCode handler.
But I allways like to follow new trends if I could. At least I would like to try that.
Thank you very much!
An alternative approach , substitute direct call to .done() or .fail() by filtering responses through .always() initially , then calling .done() or .fail() through filtering deferred ; maintaining ability to process actual net errors with same fail() callback
// simulate server-side responses
var error = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<item>"
+ "<name>message</name>"
+ "<value>Invalid input data</value>"
+ "</item>";
var success = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<item>"
+ "<name>message</name>"
+ "<value>Success</value>" + "</item>";
// params
$.ajaxSetup({
beforeSend : function(jqxhr, settings) {
var d = decodeURIComponent(settings.data)
.match(/data=+.*/)[0]
.split(/=|&/);
var params = {};
params[d[0]] = {};
params[d[0]][d[1]] = d[2];
params[d[0]][d[3]] = d[4];
jqxhr.data = params;
}
});
var request = function (url, _xmlResponse, data1, data2) {
var _response = new $.Deferred(),
_request = $.ajax({
url: url,
type: "POST",
data: {
// responses
xml: _xmlResponse,
// params
data: "param1="+ data1 +"¶m2="+ data2
},
dataType: "xml"
});
// check `responseText` for "Invalid" ,
// check `textStatus` for actual net error , "error"
_request.always(function (xml, textStatus, jqxhr) {
console.log(xml, textStatus, jqxhr, "check");
// simulate server-side processing, cont.
// if both object passed to server ,
// `param1` and `param2` _do not_ have property
// with value of at `params` , `""` empty string - generic "error" ,
// _and_ returned `responseText` contain "Invalid" ,
// _or_ `textStatus` : `error` , `reject` `dfd` , call `.fail()`
// else `resolve `dfd` , call `.done()`
// check params
var test = [xml["data"] || jqxhr["data"]].every(function(v, k) {
return !(v.data["param1"] !== "" && v.data["param2"] !== "" )
}) ;
// check `xml` responseText for node for "Invalid" text ,
// generate `.fail()`
var check = $(xml.children)
.find("value").is(":contains(Invalid)");
return check && test || textStatus === "error"
// call `.fail()`
? _response.reject([xml, textStatus, jqxhr])
// call `.done()`
: _response.resolve([xml, textStatus, jqxhr])
});
return _response
.done(function (xml) {
// do `done()` stuff
console.log(xml[0], xml[1], xml[2]);
var msg = $(xml[0].children).find("value").html();
$("#success")
.html(msg + ", "
+ xml[2].data.data.param1
+ xml[2].data.data.param2
);
return this.promise()
})
.fail(function (xml) {
// do `.fail()` stuff
console.log(xml[0], xml[1], xml[2], "fail");
var msg = $(xml[0].children).find("value").html()
|| xml[1] + ", " + xml[2];
$("#error")
.html(msg);
return this.promise()
});
};
Could then call request() , without _xmlResponse param , which should handle both generated .fail() (if responseText contains "Invalid") and net error .fail() calls (e.g., statusCode 500; textStatus error) , and .done() calls .
request("someAction.do", "param1_param", "param2_param");
Optionally, chain returned promise from request at .always() , as data array containing request return values ; after being processed at .done() or fail()
request("someAction.do", "param1_param", "param2_param")
.always(function(data) {
// do `.done()` , `.fail()` stuff ,
// `data, textStatus, jqxhr`
console.log(data[0], data[1], data[2])
})
jsfiddle http://jsfiddle.net/guest271314/ek15krb5/
I think that depends on the parameter "xml", if:
1. xml is a real xml object ,it'll trigger 'done';
2. xml is not a xml object ,it'll trigger 'fail'
Even if you return a 500 error code ,it is still a valid xml object, So it'll trigger "done"
I'm using php json_encode to send a bunch of values to a client, where jquery
{"data":{"application":{"basics":{"email":"jepp#mily.com","name_first":"Step","name_last":"Bob","phone":"9210938102938","occupation":"unemployed","website":"wwwcom"},"application":{"title":"Default title","guid":"9as8ua9sd8ua9sdu","language":"sv"},"job":{"title":"joburl","url":"joburl"},"letter":{"letter":"abadbabkbakbakbakbakbakbabk"},"work-experiences":[{"title":"Default WORK Experience Title","url":"wwwsscom","date_from":"1970-01-01","date_to":"1999-12-31"},{"title":"Default WORK Experience Title","url":"wwwsscom","date_from":"1970-01-01","date_to":"1999-12-31"},{"title":"Default WORK Experience Title","url":"wwwsscom","date_from":"1970-01-01","date_to":"1999-12-31"}],"educations":{"title":"Default Education","url":"ixi","date_from":"1970-01-01","date_to":"1999-12-31"},"skills":{"title":"Defailt SKILL","url":"wwwsdcom","date_from":"ixi","date_to":"ixi"},"work-samples":{"title":"A sample of my work","url":"wwwsdcom","date_from":"ixi","date_to":"1999-12-31"}}},"error":[],"warning":[]}
If I try to parse this with $.parseJSON in a script I get no object. However, if I copy/paste it directly into the console (and add ' in the beginning and end), it works. There are no error codes and I can see no linebreaks. JSON lint-tools returns no errors...
I have set the correct content type and tried the different json parsers that jquery provides.
What have I missed?
The code was cut/pasted from the jQuery tutorials. I tried some different examples but they all failed.
var jqxhr = $.getJSON( "application_controller.php", function() {
console.log( "success" );
})
.done(function() {
console.log( "second success" );
})
.fail(function() {
console.log( "error" );
})
.always(function(data) {
console.log( "complete" );
application = data;
});
// Perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function() {
console.log( "second complete" );
});
});
It's true, I decoded it in the console. this is a snippet that does in in-script (it also won't work):
$.ajax({
dataType: "json",
contentType: "application/json",
url: 'application_controller.php',
data: '{id:id}',
success: function( data ) {
application = data.responseText;
application = $.parseJSON(application);/* < string */
},
fail: console.log("fail"),
complete: function(data) {
console.log(data.responseText);
application = data.responseText;
}
});
Answering my own question:
To solve this error I had to change all my php files from "utf8" encoding to "utf8 without BOM". Then it worked.
When a file without utf8 encoding was included (low in the hierarchy of course) it tainted all the other files and corrupted the output.
use JSON.parse(jsonString) function.
var jsonString = '{"data":{"application":{"basics":{"email":"jepp#mily.com","name_first":"Step","name_last":"Bob","phone":"9210938102938","occupation":"unemployed","website":"wwwcom"},"application":{"title":"Default title","guid":"9as8ua9sd8ua9sdu","language":"sv"},"job":{"title":"joburl","url":"joburl"},"letter":{"letter":"abadbabkbakbakbakbakbakbabk"},"work-experiences":[{"title":"Default WORK Experience Title","url":"wwwsscom","date_from":"1970-01-01","date_to":"1999-12-31"},{"title":"Default WORK Experience Title","url":"wwwsscom","date_from":"1970-01-01","date_to":"1999-12-31"},{"title":"Default WORK Experience Title","url":"wwwsscom","date_from":"1970-01-01","date_to":"1999-12-31"}],"educations":{"title":"Default Education","url":"ixi","date_from":"1970-01-01","date_to":"1999-12-31"},"skills":{"title":"Defailt SKILL","url":"wwwsdcom","date_from":"ixi","date_to":"ixi"},"work-samples":{"title":"A sample of my work","url":"wwwsdcom","date_from":"ixi","date_to":"1999-12-31"}}},"error":[],"warning":[]}';
var myData = JSON.parse(jsonString);
Fiddle
I'm trying to get weather data from openweathermap. This url works with coordinates I put in, and I can download the JSON when I input the url the in the browser bar. I'm trying to get this working in my page. When I run this code, in Firebug I can see the HTTP request got the 200 success code, but it's not printing the response for some reason. Am I not using getJSON properly?
var url = "http://api.openweathermap.org/data/2.5/forecast?lat="+ position.coords.latitude +"&lon=" + position.coords.longitude;
$.getJSON(url, function(res) {
console.log(res);
});
You are trying to read cross domain JSON in a function which reads JSONP.
Cross domain JSON reading is not possible.
Try a JSONP request instead;, by appending a callback
var url = "http://api.openweathermap.org/data/2.5/forecast?lat=" +
position.coords.latitude +"&lon=" + position.coords.longitude + "&callback=?" ;
$.getJSON(url, function(res) {
console.log(res);
});
JSON response is like this :
{ 'a':22 }
JSONP response is like :
myFunction({'a':22} ) , where myFunction was the value passed as callback
jQuery does not need the name of the callback function, however needs callback to be mentioned in the URL so that it can indentify it as a JSONP request.
JSONP
If the URL includes the string "callback=?" (or similar, as defined by
the server-side API), the request is treated as JSONP instead. See the
discussion of the jsonp data type in $.ajax() for more details.
Append this ?callback=? to the url and try again like:
$.getJSON(url + '?callback=?', function(res) {
console.log(res);
});
Try this
function buildQuery() {
var str = "http://api.openweathermap.org/data/2.5/forecast?lat=27.175009&lon=78.041849";
return "select * from json where url ='" + str + "' ";
}
$.ajax({
url: 'http://query.yahooapis.com/v1/public/yql',
data: {
q: buildQuery(),
format: "json"
},
dataType: "jsonp",
success: function (data) {
alert(JSON.stringify(data));
},
error: function (data) {
consol.log(data);
}
});
working Demo :-
http://jsfiddle.net/HWuDk/1/
I'm trying to fetch a custom JSON feed I have written with jQuery using the getJSON method. For an unknown reason the URL seems to be having cache_gen.php?location=PL4 stripped from the end and replaced with [object%20Object] resulting in a 404 error occurring.
Here's the jQuery I'm using:
var fetchData = function() {
if (Modernizr.localstorage) {
var api_location = "http://weatherapp.dev/cache_gen.php";
var user_location = "PL4";
var date = new Date();
console.log(api_location + '?location=' + user_location);
jQuery.getJSON({
type: "GET",
url: api_location + '?location=' + user_location,
dataType: "json",
success: function(jsonData) {
console.log(jsonData);
}
});
} else {
alert('Your browser is not yet supported. Please upgrade to either Google Chrome or Safari.');
}
}
fetchData();
From the console log I can see the URL string is calculated correctly as: http://weatherapp.dev/cache_gen.php?location=PL4
However the second line in the console is: Failed to load resource: the server responded with a status of 404 (Not Found).
Can anyone point me in the right direction with this?
UPDATE 19/01/2013 23:15
Well, I've just converted so that is fits the docs perfectly using $.ajax. I've also added a fail event and logged all of the data that gets passed to it.
var fetchData = function() {
if (Modernizr.localstorage) {
var api_location = "http://weatherapp.dev/cache_gen.php";
var user_location = "PL4";
var date = new Date();
var url = api_location + '?location=' + user_location;
console.log(url);
jQuery.ajax({
type: "GET",
url: api_location + '?location=' + user_location,
dataType: "json",
success: function(jsonData) {
console.log(jsonData);
},
error: function( jqXHR, textStatus, errorThrown ) {
console.log('textStatus: ' + textStatus );
console.log('errorThrown: ' + errorThrown );
console.log('jqXHR' + jqXHR);
}
});
} else {
alert('Your browser is not yet supported. Please upgrade to either Google Chrome or Safari.');
}
}
fetchData();
After this my console gives me the following information:
http://weatherapp.dev/cache_gen.php?location=PL4
download_api.js:44textStatus: parsererror
download_api.js:45errorThrown: SyntaxError: JSON Parse error: Unable to parse JSON string
download_api.js:46jqXHR[object Object]
I have ensured the headers for the JSON feed are current, and the feed is definitely serving valid JSON (it effectively caches a 3rd party service feed to save costs on the API).
The reason why you see this error:
http://weatherapp.dev/cache_gen.php?location=PL4
download_api.js:44textStatus: parsererror
download_api.js:45errorThrown: SyntaxError: JSON Parse error: Unable to parse JSON string
download_api.js:46jqXHR[object Object]
Is because your JSON is invalid. Even if a response comes back from the server correctly, if your dataType is 'json' and the returned response is not properly formatted JSON, jQuery will execute the error function parameter.
http://jsonlint.com is a really quick and easy way to verify the validity of your JSON string.
I was running into the same issue today. In my case I was assigning a JSON object to a variable named 'location' which is a reserved word in JavaScript under Windows and appearantly is a shorthand for windows.location! So the browser redirected to the current URL with [object%20Object] appended to it. Simple use a variable name other than 'location' if the same thing happens to you. Hope this helps someone.
Check out the actual function usage:
http://api.jquery.com/jQuery.getJSON/
You can't pass on object parameter into $.getJSON like with $.ajax, your code should look like this:
jQuery.getJSON('api_location + '?location=' + user_location)
.done(function() {
//success here
})
.fail(function() {
//fail here
});
To maybe make it a little clearer, $.getJSON is just a "wrapper function" that eventually calls $.ajax with {type:'get',dataType:'JSON'}. You can see this in the link I provided above.
I am using backbone-tastypie, but I am having the toughest time getting it to work properly. In Tastypie, I am using ApiKeyAuthentication for my resources, so every ajax request, I need to append the apikey and username to the end of a request or send additional headers that add on the username and api key.
I am trying to remove a view and its model using backbone with the following code:
// Remove the goal update view from the DOM
removeItem: function() {
this.model.destroy({wait: true, success: function() {
console.log("success");
}, error: function() {
console.log("error");
}});
},
After the function executes, the browser tries to do a GET request on the following URL:
:8000/api/v1/update/2/
It does not include the api_key or username at the end, and it has a trailing slash at the end of the url. I think it is trying to use Backbone.oldSync to do the GET request. How would I make it so the sync does include the username/api key at the end and removes the trailing slash?
In all of the other requests, I have made it so the api key and username is appended to the end of the http request by adding the following code to backbone-tastypie:
if ( !resp && ( xhr.status === 201 || xhr.status === 202 || xhr.status === 204 ) ) { // 201 CREATED, 202 ACCEPTED or 204 NO CONTENT; response null or empty.
var location = xhr.getResponseHeader( 'Location' ) || model.id;
return $.ajax( {
url: location + "?" + "username=" + window.app.settings.credentials.username + "&api_key=" + window.app.settings.credentials.api_key,
success: dfd.resolve,
error: dfd.reject,
});
}
Let's explore the possibilities
Using headers
Backbone.sync still just uses jQuery ajax so you can override ajaxSend and use headers to send information along.
$(document).ajaxSend(function(e, xhr, options)
{
xhr.setRequestHeader("username", window.app.settings.credentials.username);
xhr.setRequestHeader("api_key", window.app.settings.credentials.api_key);
});
Using Ajax Options
If you need to send the information in just one or two locations, remember that the destroy, fetch, update and save methods are just shortcuts to the ajax caller. So you can add all jQuery ajax parameters to these methods as such:
// Remove the goal update view from the DOM
removeItem: function ()
{
this.model.destroy({
wait: true,
success: function ()
{
console.log("success");
},
error: function ()
{
console.log("error");
},
data:
{
username: window.app.settings.credentials.username,
api_key: window.app.settings.credentials.api_key
}
});
}
Overriding jQuery's ajax method
Depending on your needs, this might be the better implementation (note that this is no production code, you may need to modify this to fit your needs and test this before using it)
(function ($) {
var _ajax = $.ajax;
$.extend(
{
ajax: function (options)
{
var data = options.data || {};
data = _.defaults(data, {
username: window.app.settings.credentials.username,
api_key: window.app.settings.credentials.api_key
});
options.data = data;
return _ajax.call(this, options);
}
});
})(jQuery);
Just for future readers of this post, when you do a model.destroy() you can't pass any data because the delete request doesn't have a body, see this issue for more info:
https://github.com/documentcloud/backbone/issues/789