Link to home
Start Free TrialLog in
Avatar of elepil
elepil

asked on

My jquery .ajax() keeps invoking .fail() handler when result is successful, why??

Here's how my jQuery .ajax() call looks like on my login.php page:

$.ajax({
                            method: "POST",
                            url: "/_includes/_db/processLogin.php",
                            dataType: "json",
                            data: { username: $("#txtUserName").val(), 
                                    password: $("#txtPassword").val() }
                        })
                        .done(function(data, textStatus, jqXHR) {
alert("It hit done.");
                        })
                        .fail(function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status); // IT KEEPS LANDING HERE AND PRINTS OUT 200, WHICH IS OK.
                        });

Open in new window


The PHP script (processLogin.php) contains this code excerpt:

try {
        $db = DB::getPDOConnection();
        // Turn on Exception throwing
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch (Exception $e) {
        $userMessage = "FATAL ERROR!";
        $arrResponse = array('result'=>'fail', 'message'=>$userMessage);
        echo json_encode($arrResponse);
        exit;
    }

Open in new window


Now I intentionally misspelled the host name to force an error, and I have confirmed that code execution does reach the catch block. But given the way it is, the .ajax() on the client side is firing off the .fail() handler instead of the .done(), and I can't figure out why. I could've sworn this used to work, and it just stopped working all of a sudden.

Can anyone see any reason why the .ajax() would fire the .fail() handler instead of the .done()?

Thanks.
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Check the last example on this page.  They do not use chained methods.
http://api.jquery.com/jquery.ajax/
Avatar of elepil
elepil

ASKER

Ray,

I don't know the purpose of your providing that link, nor do I know what you mean by "chained" methods. Are you talking about my throwing Exceptions again? Because that is on the PHP side. As far as the .ajax() call, I imagine all it should care about is what I'm echoing out of my PHP script, right?
SOLUTION
Avatar of Dave Baldwin
Dave Baldwin
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I think you will see the purpose of that link if you look at the last example on the page, reproduced here for your convenience:
var menuId = $( "ul.nav" ).first().attr( "id" );
var request = $.ajax({
  url: "script.php",
  method: "POST",
  data: { id : menuId },
  dataType: "html"
});
 
request.done(function( msg ) {
  $( "#log" ).html( msg );
});
 
request.fail(function( jqXHR, textStatus ) {
  alert( "Request failed: " + textStatus );
});

Open in new window

Notice how the example defines request.done() and request.fail() as separate closures.  Chained methods are the way your original code snippet showed the .done() and .fail() methods written as part of the $.ajax() statement.  That's the client-side part of things.  It might be easier to follow the example in the online manual.

In the PHP code snippet, it appears that your script may echo what looks like a failure response (if an exception is thrown), but I can't see where it runs a query, so I'm a little confused about how it might return data.  And the PHP definition of success or failure is not the same as the jQuery definition.  This article explains some of the ideas:
https://github.com/jquery/api.jquery.com/issues/49

When I develop AJAX-type interactions, I start by developing the server-side of the action.  You can test this from the browser address bar if you use $_REQUEST, which covers both $_GET and $_POST.  Your URL parameters can be injected directly into the request variables.  Once you're satisfied that the script works, change out $_REQUEST and use only $_POST.
Avatar of elepil

ASKER

Dave,

I should mention that this code has been working for a while now. It has been part of my procedure to test my error-handling routine by intentionally misspelling my server name from 'localhost' to 'localhos' to make it bomb out. It has always been invoking the .done(), not the .fail(). I am totally perplexed why it's doing this now, and I find it even more incredulous that I now should change the code when it was working fine before. Something else is causing this.
This demo from the middle of the page works fine.  Is the formatting different and I just don't recognize it?

/ Assign handlers immediately after making the request,
// and remember the jqXHR object for this request
var jqxhr = $.ajax( "example.php" )
  .done(function() {
    alert( "success" );
  })
  .fail(function() {
    alert( "error" );
  })
  .always(function() {
    alert( "complete" );
  });
 
// Perform other work here ...
 
// Set another completion function for the request above
jqxhr.always(function() {
  alert( "second complete" );
});

Open in new window

elipil, look for typos...  Also... I never take it as a guarantee that just because the code was working that I didn't miss something that didn't work but was always in there.  I've done that a couple of times.  When the right 'trigger' comes along, it failed.
Is "/_includes/_db/processLogin.php" actually returning JSON formatted data?
Avatar of elepil

ASKER

Dave,

Yes, and I know this because I set a breakpoint on where my array was being given the two elements of 'result' and 'message'. It executes the echo json_encode($arrResponse) just fine, too, even the final 'exit' statement. So despite everything looking normal to me as I step trace it line by line, it ends up in the .fail() handler back on the .ajax() side.

I get so frustrated with PHP/jQuery/JavaScript when these things happen. I thought I was done with this part, and now I have to revisit it again.
When you mix them all together, you Never get away from it.  How do you think Ray and I stay employed?  There is always something...

Since an AJAX POST (or GET) is just a different way of doing an HTML <form>, sometimes I create a simple form page to POST and display the returned data.  That would give you another view to the problem that does not include javascript or AJAX.
I am looking at the code here:
https://www.experts-exchange.com/viewCodeSnippet.jsp?refID=28675907&rtid=10&icsi=2

Here it is annotated with comments.  It does not make sense to me because it never runs a query nor returns any data unless there is an Exception.

// WRAP THE FOLLOWING STATEMENTS IN A TRY / CATCH BLOCK
// TRY TO DO SOMETHING
try {

    // THIS APPEARS TO RUN A STATIC METHOD CALL TO ASSIGN A VALUE TO THE $db VARIABLE
    $db = DB::getPDOConnection();
    
    // THIS APPEARS TO SET SOME ATTRIBUTES ON THE $db OBJECT
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
// IF NOTHING THREW AN EXCEPTION, THE CATCH BLOCK WILL NOT BE RUN
// ONLY IF SOMETHING IN THE TRY BLOCK THREW AN EXCEPTION WILL WE EVER SEE THIS CODE EXECUTEDD
} catch (Exception $e) {
    $userMessage = "FATAL ERROR!";
    $arrResponse = array('result'=>'fail', 'message'=>$userMessage);
    echo json_encode($arrResponse);
    exit;
}

// SO AFTER THE TRY BLOCK IS EXECUTED, THE SCRIPT WILL BE HERE, DOING WHATEVER IS CODED HERE

Open in new window

ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
@Dave: ^^ +1 for that !
Avatar of elepil

ASKER

I recently had to reinstall my Windows OS. The day before that, I did one whole day's work that enhanced my error-handling routines which I unfortunately didn't backup before my hard drive crash. But everything was working PERFECTLY. After a lot of grief from having to bring my system back to the shape it was prior to the crash, I started recreating what I lost, and this happens. This did NOT happen before.

Dave, I know what you're talking about, I've had bugs that didn't appear until 1 1/2 years later. But this is different. NO CHANGES were made that could even have this effect. After I do "json_encode($arrResponse);", it's also out of my hands. What happens from that point until it reaches the front end is out of my reach. So I really don't know what I can do.

Ray, you don't need to see my query. My sample could very well just have been a straight array creation of anything followed by a json_encode($array) function call, and that's when this issue comes up.
Ray, you don't need to see my query.
Really?  OK, I'm out.  

I do not depend on rumors or expectations or anything like that -- I depend on test-driven development because I know it works, and so does the rest of the professional industry.  So when the question is postulated with unproven assertions, I know it's time to let someone else try to help.  The SSCCE is a really good idea; I can install it and test it.  And in my experience (more years than I care to admit) anything less is just irresponsible.

Best of luck with your project, ~Ray
Avatar of elepil

ASKER

Ray,

You're totally missing the point of the problem. It so happens I was using a query to cause the catch block to execute which contained the code to echo a json string back to the client.

Didn't you see Dave's post that he copied/pasted my code and he got the same thing? I'll bet you he has no query.
Avatar of elepil

ASKER

You know what, screw this. This only happens when I changed my 'localhost' to 'localhos' to force a database connection failure. All other error handling sections function normally without this issue. I have no idea why this is happening, and I really shouldn't spend more time on this anymore. I'm falling behind on my project.

Thanks to all who responded.
Didn't you see Dave's post that he copied/pasted my code and he got the same thing?
You misunderstood me.  I copied the code from http://api.jquery.com/jquery.ajax/ and it worked perfectly.  http://www.dibsplace.com/webdev/jqxhr-function-tests.html

Ray and I are pretty good with code.  When you say that we don't need to see code, that lowers our interest in helping you.