I build JQuery/JS/PHP/mySQL app with DB records management and need to provide reliable & complete feedback to the user on AJAX calls, modifying back end DB records. The problem IMHO is $.ajax success: and error: functions indicate just AJAX transport layer success and not the whole process. What if DB modification fail? How can one provide the complete feedback to the user?
I ended up with
$.ajax({
url: "/action/delete",
data: "rowid="+rowid,
complete: function(xmlHttp) {
if ( xmlHttp.responseText ) alert('Success - back end returned "success"');
else alert('failure - back end returned NULL')
}
});
and PHP response:
$success = deleteRecord( $_GET(rowid) );
if($success) {
print 'success';
} else {
print NULL;
}
exit();
The idea is simple - if I manage to get positive feedback from the back end, then the whole operation succeeded, if not - user don't care where problem occurred.
Thank you in advance, your feedback is highly appreciated.
If you respond to the request with some json data instead of just some new html to insert into the DOM, you can place whatever kinds of error codes and messages you like with the data. For example, if your response was something like...
{
errorstate: 0,
errormsg: "All systems are go",
displaytext: "stuff I want to display when all goes well"
}
Your javascript code can examine this data and do whatever it feels it needs to. It also allows you to push more of the error handling into your server script which can often be simpler.
Try http://docs.jquery.com/Ajax/jQuery.getJSON#urldatacallback
One possible solution would be to use the HTTP response code to signal a failure, like 200 OK, everything's ok, and 500 Internal Server Error on error, which you can simply check when you reach state 4.
In PHP I believe this is done through header("HTTP/1.0 200 Ok") before any other data is sent. If you're afraid data will be sent by mistake before you can evaluate the correct header to set you can turn on output buffering.
How you wish to present the data is of course up to you, you could for example on 500 just have document.getElementById("myerrorbox").innerHTML = xmlHttp.responseText, or similar, and render a partial html-document in your php-program.
I send status messages back to the client. Along with the error flag. And then my JavaScript code displays the message it got from the server, and colours the message according to the error flag.
I find that to be quite efficient.
Related
I'm not sure if I'm going about this the wrong way or not and unable to find what I'm after so if someone can point out my mistake or let me know if I'm going down the wrong road that'd be great.
I am trying to post form data to another file using $.post('example.php',data1:foo,data2:bar}). The example.php page contains an INSERT sql query.
After this is executed, and the example.php page inserts the posted data into the DB, how can I get either a pass/fail/ANYTHING returned?
I have tried various $.post('..php',{data..},function(data){}) examples I've seen on here and other sites, but the success function seems to return no matter what, even if there are glaring problems in the INSERT statement.
Here is an example of my code:
//validate transaction form
$("#frmTransaction").validate({
submitHandler: function(element) {
hidePageMessages();
var invnum = document.frmTransaction.invnum.value;
var recnum = document.frmTransaction.recnum.value;
var status = document.frmTransaction.status.value;
$.post("tran_add.php",
{
invnum:invnum,
recnum:recnum,
status:status
},
function(data){
my_function(data)
}
);
},
rules: {
description: "required",
amount: "required",
account: "required",
category: "required",
payee: "required"
},
errorClass:"errorinline",
validClass:"valid"
});
function my_function(data){
alert(data);
}
so, if the sql statement in tran_add.php is executed succesfully, THEN and ONLY THEN do I want the my_function executed, which will display as 'pass' message to the user. Does tran_add.php need to do anything other than the sql statement, ie return success or something? Or again, am I going about this the wrong way?
Thanks in advance for any help, suggestions, smacks around the back of the head for missing something obvious etc
You should do, for example:
$mySqlInsertStatement = "insert statement"
If($mySqlInsertStatement) //to check for successful insert
Echo 0
Else
Echo 3
(Of course if statement is lower case,etc. )
Then in the success statement, you should say:
If(success == 0)
//success
Else
//not success
$.post() returns data based on the data you send to the url. On your tran_add.php you need conditions like:
$mysqli->query("INSERT table (column1,column2) VALUES ('value1','value2')");
if($mysqli->affected_rows > 0){
// now return your stuff
echo json_encode(array('test' => 'worked', 'see' => 'now'));
}
To test you should change
function my_function(data){
alert(data);
}
to
function my_function(data){
// use firebug with console to see object
console.log(data);
}
Inside Function.Use $.each();
function(data){
$.each(data,function(key,value){
alert(key+""+value);
});
}
You simply need to echo the successful result, and jquery will do the rest for you.
I'm not a really experienced professional, and I have no idea what is happening behind the scenes. In my mind, it goes like this:
When php echoes a successful result, jquery/ajax sees that something is posted in the webpage after execution of script, and understands that the message means success, and executes its success function. If execution stops prematurely, and nothing is echoed or execution 'dies' prematurely or error message is echoed in an else clause, then that means that there was an error in execution, and the success function will not be run.
Hopefully someone can explain better what happens behind the scenes.
Anyway, fact of the matter is if you echo a message like "Execution Successful" in your if clause at the end of the script, only then your js success function will be executed.
I'm pretty sure the success function will be called as long as there is any response from the server that is not an error (HTTP Code 400/404/500/etc). So, you have two options:
1) have your php app Set an error if the insert is not successful:
<?php
http_response_code(502);
?>
2) have the php return some data that the success function can parse to know what happened (I recommend returning json if you can), something like:
{"result":"error" "details":"Database Insert failed..."}
Or
{"result":"success", "new_id":42}
My preference is to combine these approaches.
I have been looking around the web (obviously in wrong places) to find what is the success and failure criteria for ajax(jquery post) purposes.
For example, let's say I am using ajax to post to a php script. The script can return:
exit 0
exit 1
jason array
return
etc...
When would those return values be translated into success and when into failure?
As you may already know $.ajax() supports beforeSend, success, error and complete callbacks.
So what should my script send in case of success and in case of failure for the appropriate callback to be triggered.
Ben is right, but I'll expand a little.
jQuery determines success or failure based on the HTTP response code of the page being called. Note that this is not the same as the content in the response that is sent back.
As an example, let's say that you have your PHP script located at http://url.com/script.php
When a user hits that site, they are going to get a response from the server. That response could be a JSON object, it could be an HTML page, or it could be an empty response. In all of these cases, the response code would likely be 200. A 200 response code means that the server understood the request, accepted it, and sent something back.
Now let's say that a user tries to hit http://url.com/notascript.php
The server doesn't know what to do with that (assuming that notascript.php doesn't actually exist). It fails the request, and sends back a response -- probably with the response code 404 (or something else in the 4xx range).
So if you know the actual URL, then how does jQuery's error handler ever get called?
Well, let's say that your AJAX call is trying to load a blog post, and tries to make a call like this: http://url.com/post?id=5. If your PHP script determines that there is no blog entry with an ID of 5, then you probably shouldn't send back a successful response. Rather, a 4xx response would be more appropriate. And PHP has a built-in function for that:
<?php
http_response_code(404);
?>
Now, the response will be read by jQuery as a failure, and the error handler will be called.
Further reading:
http_response_code() function
RFC2616, which defines HTTP response codes
REST
I believe it's based on header codes (ie, 200 - success). You can send your own special errors back though e.g. How to receive error in jQuery AJAX response?
You shouldn't make Ajax error if you have a problem with the code in the page being requested. As far as Ajax is concerned, so long as the page physically is successfully requested, it has performed properly. Any errors within the page being requested are not a fault of Ajax, so should be handled by your code after a successful load of that page. Using custom headers as in the link above will make it easier for you to do that.
Ajax requests page --> Page loads & no errors --> page request successful --> You Perform result error checking
vs
Ajax requests page --> Page loads & has errors --> page request successful --> You Perform result error checking
As you can see, it doesn't matter if the page being requested has errors, it's not an Ajax fault, so shouldn't be treated as one.
You can select one pattern that always printed for success, other cases like ajax failure can be known via AJAX itself (HTTP response code): for example:
You always print: yes for success and if correct result found
You always print: no for success and if incorrect result found
If none of above returned then its ajax failure or if the script prints another word then you need to check your PHP.
A quick question of perhaps a more speculative nature. I've been getting heavy into jquery lately to handle all the ajax in my web apps.
Right now I'm building a bidding system in PHP that makes heavy use of mod_rewrite. I'm using jQuery with a confirm dialog to send an Ajax request that will spend some of the user's predeposited credits on a bid. The ajax request to spend is sent with the cost as a post parameter to a PHP controller that spends the users credits and then echos the output, which jQuery then places back into the document.
It's working fine, but what I'm wondering is if there is a better way to make jQuery handle the refusal of the purchase if the user has insufficient credits. Right now I have the php answering with an echo that displays this message with a link to the make a deposit page... but I'd rather have a redirect happen automatically.
Is there some way my jQuery script could be notified with the boolean of success or failure before .load finishes, and then redirect in the case of failure? Possibly through HTTP headers determining the handling? The only way I could think of is to place a true or false in an html element that gets check in the callback after .load() and in the case of a false perform a redirect.
Thanks and sorry for the explanation length.
If every bidding attempt requires going somewhere else, why use AJAX in the first place?
Anyway, if you look at jQuery's API documentation you'll see that load() is not the only function available. Most of the are simplified versions of ajax(); if you use this one, you can control all possible events right from there. No need to mess with HTTP headers!
I suggest you redesign your server-side script so it returns a JSON object. Then, you can send back all the different types of responses:
{
biddingSuccessful: true,
linkToDepositPage: "http://example.com",
textToDisplay: "Your bidding was successful"
}
Use the lower level $.ajax call to have full maximum control over the request. Ideally, instead of sending a success 2xx response, send an error response which will automatically get sent to your error callback.
$.ajax({
url: '..',
success: function() {
// if it gets here, then assume credits were used
},
error: function() {
// some error happened
// if error was about insufficient funds, then redirect
}
});
From the server, send the success response as you are doing right now. However for errors, change the response header, and send a JSON object or plain text indicating what the error was. And there is a header for exactly what you are looking for. It's 402 - Payment Required :)
header('HTTP/1.1 402 Payment Required');
send a JSON object as response with more details:
{
status: 'error',
reason: 'Insufficient Funds',
balance: '$2.78',
amountRequested: '$3.50'
}
For the updated comment, you need to use a closure (better than global variables :)
Suppose the outer function gets the element name/ID, wraps that value through a closure in the success callback. Please let me know if this is not what you intended.
function makeAJAXCall(elementName) {
$.ajax({
success: function(...) {
// elementName is available here through a closure
alert(elementName);
}
});
}
if the callback function is like "function (data) {" then you could return "NSF" or something like that, and simply compare 'data' to 'NSF', and do the redirection with window.location
How do ajax know whether it failed or succeeded if server side doesn't echo anything back?
$.ajax(error:..,success:..)
I met with this exception in my test:
uncaught exception: [Exception...
"Component returned failure code:
0x80040111 (NS_ERROR_NOT_AVAILABLE)
[nsIXMLHttpRequest.statusText]"
nsresult: "0x80040111
(NS_ERROR_NOT_AVAILABLE)" location:
"JS frame ::
http://localhost/script/tab.js ::
anonymous :: line 69" data: no]
The server side code is :
$id = process();
And for the purpose of testing,I have exit() in process();
Is that the reason for this exception?If so,why?
EDIT
I looked over to the line that cause exception,it's the error handling function of $.ajax()
error:function(XMLHttpRequest, textStatus, errorThrown){
alert(XMLHttpRequest.statusText);alert(textStatus);alert(errorThrown);
}
Anything wrong here?
The httprequest also returns a status such as 200 == ok, 404 == not found, 12152 == connection closed by server and so on..
Just read up on the status id's what they mean so you can look for them. you can also for debugging reasons just write out myhttprequest.status to the document and it shows what status it returned.
This depends on the status code the request returns. A successful request returns a status code in the range of 2xx, an error is in the range of 4xx of 5xx.
For more information see Wikipedia: List of HTTP status codes.
It would still get a response from the server, with the data part of it being empty. If it got no response at all, that would be an error.
http://docs.jquery.com/Ajax/jQuery.ajax#options
Give an option for success and error These functions will be called after the call is made.
There are four possible scenarios that you could get:
the server isn't there or refuses the connection (this is identifiable by the sockets library that the browser uses, which will report the connection failure)
the connection works and the server returns a non-success error code - this comes back in the header. Indeed, the request can succeed (200 code) even with an empty body, that's perfectly valid
the connection comes up but the server fails to respond - I'm not clear on the details of this, but i'd expect the JS to eventually time out because no response was received and return a failure based on that.
the connection comes up but the server responds incorrectly (e.g. no headers) - the JS implementation should return this as an error.
In any case, all the error scenarios are handled by the Javascript core's XMLHttpRequest implementation - jQuery just wraps it up with slightly tidier interface.
In your case (now you've provided more information) I would recommend that you use Firebug to see what the server response to your request is. That said, you shouldn't be getting an exception for anything inappropriate from the server, the JS should call the same error callback for all the above cases.
are you missing { } ?
$.ajax(error:..,success:..)
should be
$.ajax( { error: function( ){ } } );
if that's it, sorry dude, that would be annoying to have spent that much time on, haha
I fixed this by specifying a timeout in my ajax call. The ajax timeout was just giving up after X amount of time. Even though the page ended up returning data, the ajax object just gave up and bailed, but threw this error.
i have a page performing the following ajax request when a button is pressed.
normally i get a json object back and it works fine, i have noticed on intermittent requests (usually only the first request from that page), i get back a 200 success code with a blank page.
if i reload the html page, then press the button again it works fine straight afterwards.
by intermittent i mean i can't replicate the issue at will, but it is happening regularly enough that i need to do something about it
i am just wondering if it is most likely an ajax or in particular a prototype problem or a server side issue (i am using debian/apahce/php)
what can i try to track down the problem ?
new Ajax.Request( url,
{
method:'post',
parameters: $('TeamForm').serialize(true),
onSuccess: function(transport) {
// do stuff
},
onFailure: function(transport) {
// display error
}
});
This isn't a solution to your problem but a workaround -- in the meantime, you could detect if the response's responseJSON property is NULL, and if so, log the error and resubmit the request. That way at least the second request should go through. The easiest way to handle this might be to throw a custom object from your onSuccess handler allowing your onFailure handler to catch it and resubmit.
Based on the example you provided, the only source of concern I can see with the javascript is the $('TeamForm').serialize(true); statement. Are you sure that the TeamForm has well formed data, and your PHP backend is handling this appropriately?
Check your PHP code for any trailing whitespace. You should not end your PHP files with a closing tag.
e.g.
<?php
class Foo {
}
?> //There is a space after this closing tag!
Would result in the hidden space being sent to your browser. It is valid syntax (and recommended) to leave the closing tag off of a pure PHP file:
<?php
class Foo {
}
Also check your code for any echo's or print's that may send output to the browser. Also check your display_errors setting, as an error message could result in data being sent to the browser as well.
I'd put 99:1 odds on the problem being server-side.