Ajax fails 5% of time, response is "error" - javascript

I'm using jQuery to handle Ajax-calls.
I've noticed that, about 5% off the time, the ajax call fails. To make sure I get a good understanding of what's going wrong, I use this code:
$.ajax({
type:'POST',
url:'somepage.php',
data:{somedata:somedata},
success:function (data) {
var IS_JSON = true;
try
{
var newdata = jQuery.parseJSON(data);
}
catch(err)
{
IS_JSON = false;
}
if(IS_JSON)
{
//this is the part where a correct response is handled
}
else
{
//In case somepage.php gives a php-error, I put the exact error (=data) in the error-table at error.php.
window.location = "error.php?errorstring="+data;
}
},
error:function (XMLHttpRequest, textStatus, errorThrown) {
//In case the ajax errors, I store the response (timeout, error, ...) in the database at error.php
window.location = "error.php?errorstring="+textStatus;
}
});
"Good" responses contain JSON, which I parse. If it's not JSON (for example just raw text from an php error) I don't try to parse it, but store the error in my database.
I would understand errors containing php errors that occured on somepage.php (since it's quiet a large page), but I'm supprised that the main errors I get, are errors of the ajax failing. The response data is just "error".
Anyone knows what the cause could be? What causes ajax-calls to fail? It's not a timeout, and it's also nothing like that somepage.php wasn't found or something. It's also not an error on somepage.php, since in that case, the Ajax-call would be successful, and the php-error would be logged in my database.
Edit: I used this obfuscator to make the script a little harder to read... Don't know if this could be causing the errors...

You should set dataType: 'json' in your ajax call. Coz if your not setting this up and your expecting a json result, the result will be treated as 'string' by default.

Related

.fail() fails to execute when ajax request is not successful [duplicate]

Is it possible to catch an error when using JSONP with jQuery? I've tried both the $.getJSON and $.ajax methods but neither will catch the 404 error I'm testing. Here is what I've tried (keep in mind that these all work successfully, but I want to handle the case when it fails):
jQuery.ajax({
type: "GET",
url: handlerURL,
dataType: "jsonp",
success: function(results){
alert("Success!");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Error");
}
});
And also:
jQuery.getJSON(handlerURL + "&callback=?",
function(jsonResult){
alert("Success!");
});
I've also tried adding the $.ajaxError but that didn't work either:
jQuery(document).ajaxError(function(event, request, settings){
alert("Error");
});
Here's my extensive answer to a similar question.
Here's the code:
jQuery.getJSON(handlerURL + "&callback=?",
function(jsonResult){
alert("Success!");
})
.done(function() { alert('getJSON request succeeded!'); })
.fail(function(jqXHR, textStatus, errorThrown) { alert('getJSON request failed! ' + textStatus); })
.always(function() { alert('getJSON request ended!'); });
It seems that JSONP requests that don't return a successful result never trigger any event, success or failure, and for better or worse that's apparently by design.
After searching their bug tracker, there's a patch which may be a possible solution using a timeout callback. See bug report #3442. If you can't capture the error, you can at least timeout after waiting a reasonable amount of time for success.
Detecting JSONP problems
If you don't want to download a dependency, you can detect the error state yourself. It's easy.
You will only be able to detect JSONP errors by using some sort of timeout. If there's no valid response in a certain time, then assume an error. The error could be basically anything, though.
Here's a simple way to go about checking for errors. Just use a success flag:
var success = false;
$.getJSON(url, function(json) {
success = true;
// ... whatever else your callback needs to do ...
});
// Set a 5-second (or however long you want) timeout to check for errors
setTimeout(function() {
if (!success)
{
// Handle error accordingly
alert("Houston, we have a problem.");
}
}, 5000);
As thedawnrider mentioned in comments, you could also use clearTimeout instead:
var errorTimeout = setTimeout(function() {
if (!success)
{
// Handle error accordingly
alert("Houston, we have a problem.");
}
}, 5000);
$.getJSON(url, function(json) {
clearTimeout(errorTimeout);
// ... whatever else your callback needs to do ...
});
Why? Read on...
Here's how JSONP works in a nutshell:
JSONP doesn't use XMLHttpRequest like regular AJAX requests. Instead, it injects a <script> tag into the page, where the "src" attribute is the URL of the request. The content of the response is wrapped in a Javascript function which is then executed when downloaded.
For example.
JSONP request: https://api.site.com/endpoint?this=that&callback=myFunc
Javascript will inject this script tag into the DOM:
<script src="https://api.site.com/endpoint?this=that&callback=myFunc"></script>
What happens when a <script> tag is added to the DOM? Obviously, it gets executed.
So suppose the response to this query yielded a JSON result like:
{"answer":42}
To the browser, that's the same thing as a script's source, so it gets executed. But what happens when you execute this:
<script>{"answer":42}</script>
Well, nothing. It's just an object. It doesn't get stored, saved, and nothing happens.
This is why JSONP requests wrap their results in a function. The server, which must support JSONP serialization, sees the callback parameter you specified, and returns this instead:
myFunc({"answer":42})
Then this gets executed instead:
<script>myFunc({"answer":42})</script>
... which is much more useful. Somewhere in your code is, in this case, a global function called myFunc:
myFunc(data)
{
alert("The answer to life, the universe, and everything is: " + data.answer);
}
That's it. That's the "magic" of JSONP. Then to build in a timeout check is very simple, like shown above. Make the request and immediately after, start a timeout. After X seconds, if your flag still hasn't been set, then the request timed out.
I know this question is a little old but I didn't see an answer that gives a simple solution to the problem so I figured I would share my 'simple' solution.
$.getJSON("example.json", function() {
console.log( "success" );
}).fail(function() {
console.log( "error" );
});
We can simply use the .fail() callback to check to see if an error occurred.
Hope this helps :)
If you collaborate with the provider, you could send another query string parameter being the function to callback when there's an error.
?callback=?&error=?
This is called JSONPE but it's not at all a defacto standard.
The provider then passes information to the error function to help you diagnose.
Doesn't help with comm errors though - jQuery would have to be updated to also callback the error function on timeout, as in Adam Bellaire's answer.
Seems like this is working now:
jQuery(document).ajaxError(function(event, request, settings){
alert("Error");
});
I use this to catch an JSON error
try {
$.getJSON(ajaxURL,callback).ajaxError();
} catch(err) {
alert("wow");
alert("Error : "+ err);
}
Edit: Alternatively you can get the error message also. This will let you know what the error is exactly. Try following syntax in catch block
alert("Error : " + err);
Mayby this works?
.complete(function(response, status) {
if (response.status == "404")
alert("404 Error");
else{
//Do something
}
if(status == "error")
alert("Error");
else{
//Do something
}
});
I dont know whenever the status goes in "error" mode. But i tested it with 404 and it responded
you ca explicitly handle any error number by adding this attribute in the ajax request:
statusCode: {
404: function() {
alert("page not found");
}
}
so, your code should be like this:
jQuery.ajax({
type: "GET",
statusCode: {
404: function() {
alert("page not found");
}
},
url: handlerURL,
dataType: "jsonp",
success: function(results){
alert("Success!");
},
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Error");
}
});
hope this helps you :)
I also posted this answer in stackoverflow - Error handling in getJSON calls
I know it's been a while since someone answerd here and the poster probably already got his answer either from here or from somewhere else. I do however think that this post will help anyone looking for a way to keep track of errors and timeouts while doing getJSON requests. Therefore below my answer to the question
The getJSON structure is as follows (found on http://api.jqueri.com):
$(selector).getJSON(url,data,success(data,status,xhr))
most people implement that using
$.getJSON(url, datatosend, function(data){
//do something with the data
});
where they use the url var to provide a link to the JSON data, the datatosend as a place to add the "?callback=?" and other variables that have to be send to get the correct JSON data returned, and the success funcion as a function for processing the data.
You can however add the status and xhr variables in your success function. The status variable contains one of the following strings : "success", "notmodified", "error", "timeout", or "parsererror", and the xhr variable contains the returned XMLHttpRequest object
(found on w3schools)
$.getJSON(url, datatosend, function(data, status, xhr){
if (status == "success"){
//do something with the data
}else if (status == "timeout"){
alert("Something is wrong with the connection");
}else if (status == "error" || status == "parsererror" ){
alert("An error occured");
}else{
alert("datatosend did not change");
}
});
This way it is easy to keep track of timeouts and errors without having to implement a custom timeout tracker that is started once a request is done.
Hope this helps someone still looking for an answer to this question.

$.ajax() returns syntax error: Unexpected end of json input

So I'm working on a website where I have to implement a chat, currently the whole thing is running on localhost.
I'm getting this error:
SyntaxError: Unexpected end of JSON input
and can't figure out why. I have googled a little but can't find an answer, that actually works. I actually did this yesterday, on another computer and that worked super, but today it won't work and I can't figure out why.
Thank you for the great answers.
$(function() {
updateChat("updateChat", null);
$(".chat-form").submit(function(event) {
event.preventDefault();
if ($(".chat-form input").val() != "") {
updateChat("sendMessage", $(".chat-form input").val());
}
});
setInterval(function() {
updateChat("updateChat", null);
}, 3000);
function updateChat(method, message) {
$.ajax({
type: "POST",
url: "action/chat.php",
data: {
function: method,
message: message
},
dataType: "json",
success: function(data) {
console.log(data);
},
error: function (request, status, error) {
console.log(error);
}
})
}
})
Most likely there's an error or warning in your PHP code being displayed, and because you are expecting only json, that causes the syntax error.
There are a few ways to find out what's going on:
open the developer console in your browser and see what the response is the network tab
check your PHP error log
temporarily change your dataType to html and you'll see your console.log(data)
I was getting this error due to my backend php function NOT returning a response as it should have been. It was returning nothing. My parent function that should have been returning the response was calling a child function that WAS returning a response, but the parent function wasn't passing that child return back to the ajax call.
Another possible culprit for these type of errors could be an improper python "shebang" on your back-end (server side) script.
In my particular case I had ajax call to python cgi script via Apache web server and I could not find a more descriptive error message at front-end debug tools. However, Apache logs indicated that the back-end script had problems importing a one of the python scripts because the interpreter did not recognize it. After checking the "shebang" of that back-end script sure enough it had the wrong interpreter specified because I just copied a template file over and forgot to modify it..
So, check your "shebang" at the top of your script to make sure it points to correct interpreter. Example:
For MVC controller you must return a valid JsON
return new JsonResult() { Data = new { test = 123 } };
instead of
return new JsonResult();

Using AJAX to call a php function keeps failing

im having a problem trying to get an ajax call to trigger a php function and then return successfully. As far as i can see my syntax is correct.
But all i get back is failed! Any ideas?
EDIT
I have changed my AJAX request to send without using data, just to rule out that being a problem and i have implemented some of the things people suggested below but to no avail, heres what my 2 files look like now:
ship.js:
function set_ship()
{
//var datastring = {'ship':'true'};
$.ajax({
type:'POST',
url:'soap/classes/class.ship.php',
success: function(success){
alert('success');
},
error: function(fail){
console.log(fail);
}
});
}
And my PHP class.ship.php:
<?php
var_dump("hello");
header('Content-type: application/json');
echo json_encode(array("result"=>"true"));
From the var_dump on my PHP script i can see that the class.ship.php isnt even being called for some reason.
Thanks
Please try this
json_encode(array("result"=>"true"));
because
json_encode(true) // will return just "true" which is not a valid json
Also try serializing the dataString , by doing
data: datastring.serialize();
lowercase JSON_ENCODE
success: function(success), error: function(fail)
check what is returned in network tab of firebug.
You need to set the content header to json header('Content-type: application/json'); and make sure you request return only json coz ajax is waiting only for "JSON" and it will throw parse error
if(isset($_POST['ship']) && $_POST['ship'] == "true"){
$result = "result";
header('Content-type: application/json');
echo json_encode(true);
}
I would suggest that you check what it being actually returned by the server.
The error callback receives one argument representing the xhr object, so you can inspect that directly by placing a breakpoint or using console logging, like this
error: function(xhr) {
console.log(xhr);
}
Likewise, the success callback receives three parameters: the status, the returned data and the XMLHTTPRequest Object, so you can check those in the very same way:
success: function(status, data, xhr) {
console.log(status, data, xhr);
}
You should look for the response status code and the response text in the xhr object to understand what is going wrong. If you're seeing a 200 OK response status, the data returned from the server is probably not being interpreted correctly as JSON data, so you should try setting the response header server side to application/json.
An error might occur also if something else is appended or prepended to your response. This happens especially when warnings occur in the code before returning and you have error reporting set to ON.

JavaScript Ajax (jQuery.post) Bizarre Error: state = "rejected"

So I've been trying to debug my jQuery.post() call, and have been getting some weird responses. I'm stuck on what to do next, if anyone had any suggestions, I'd really appreciate it.
<script type="text/javascript">
var debugresp;
var debugpost;
$("#scan .scanSide button.startScan").click(function() {
// ...
console.log("Scanning...");
debugpost = $.post(
"scan/scan.php",
{
"side": side
},
function(response) {
console.log(response);
/*...*/
},
"xml"
);
console.log("Sent data...");
});
<script>
The two console.log() calls outside the $.post work fine, the page returns 200 OK with valid data under the Network tab (Debug tools/Chrome), but the internal console.log(response) never fires.
If you noticed, I saved the return from $.post.
// JavaScript console, while page hasn't returned yet
debugpost.state()
// > "pending"
// After the page returns, and console.log(response) hasn't been called
debugpost.state()
// > "rejected"
I've never tried to deal with problems in jQuery.post, but I wouldn't expect "rejected" from the jqXHR that is returned from $.post.
Might anyone have more debugging suggestions or suggestions on how to approach this?
Resources:
jqXHR jQuery.post(...)
Problem solved: I had invalid XML that I was trying to parse.
For anyone else reading this, try jqXHR's fail(function(jqXHR, textStatus, errorThrown) to debug.

Debugging IFrame content

I'm having a problem with a page that works fine by itself, but when it's embedded in a iFrame in a corporate webpage (that I don't control) it chokes in IE9 (but not IE8).
The page uses jQuery to make an AJAX call and KnockoutJS to bind content for display. The page passes parameters in a GET request to my server with responds with AJAX, and it seems that it chokes when getting the data back from the server. The data is correct and correctly formatted, however, when this code executes:
$.ajax({
url: this.serviceURL + parameters,
dataType: 'json',
success: callback,
timeout: 3000,
error: function (jqXHR, status, errorThrown) {
if (status == "timeout") {
error("The connection to the server timed out.\nEither the server is down or the network is slow.\nPlease try again later.");
}
else {
error("An error occurred while trying to communicate with the server.\n " + errorThrown);
}
}
});
In IE9, I always hit the "An error occurred..." branch with the errorThrown of "SyntaxError: Invalid character", which tells me nothing.
Anybody got any suggestions on how to go about debugging this problem? I used Fiddler to look at what was being sent to and returned by the server, and everything looks fine on that end.
Update: After sleeping on it for a while, I started fresh today. What I've determined is that for some reason, when my page is iFramed, instead of getting the JSON response:
"{"Foo":true,"Bar":true}"
I'm actually getting (from forcing an error in the error handler so I could inspect the state of the jqXHR.responseText) is:
" {"Foo":true,"Bar":true}"
Which if, using the console, I try feeding to JSON.parse, gives me an error. So the question is, where the heck is that leading space coming from? If I run this in Firefox, I see the correct response from the server (no space) and if I run this outside of the iFrame, I see no leading space. So I don't think it's coming server side. Somewhere in the mess of JS running on the parent page and my page, it's inserting a leading space.
Update 2: A closer examination reveals that jqXHR.responseText.charCodeAt(0) is 65279, so it's not actually a space (although it displays as one) it is the byte order mark. But why is it there now (and not before) and why is it causing a problem?
I couldn't figure out the reason for this problem, so I hacked my way around it by adding a custom converter to my ajax call. So I now have this:
$.ajax({
url: this.serviceURL + parameters,
dataType: 'json',
success: callback,
timeout: 3000,
converters: { "text json": HackyJSONConverter },
error: function (jqXHR, status, errorThrown) {
if (status == "timeout") {
//alert("Timed out");
error("The connection to the server timed out.\nEither the server is down or the network is slow.\nPlease try again later.");
}
else {
error("An error occurred while trying to communicate with the server.\n " + errorThrown);
}
}
});
And my hacky converter looks like this:
function HackyJSONConverter(data) {
if (data[0] = 65279) {
// leading BOM - happens only with an iFrame in OT for some unknown reason
data = data.substring(1);
}
return JSON.parse(data);
}
It's immensely stupid, and I would be delighted if anybody has a better way!

Categories

Resources