14

I built a test case of an ajax call (jQuery 1.6.2) that looks like:

jQuery( document ).ready( function( $ ) {
    var test = function( x ) {
        $.ajax({
            url: 'http://www.someotherdomain.com/test.php',
            data: { x: x },
            dataType: 'jsonp',
            crossDomain: true,
            success: function( data ) { 
                console.log( data.name ); 
            },
            error: function() { 
                x++; 
                test( x ); 
            }
        });
    };
    test( 1 );
});

And the corresponding test.php file looks like:

if ( 5 > $_GET[ 'x' ] ) {
    header('HTTP/1.1 503 Service Temporarily Unavailable'); die();
} else {
    header( 'content-type: application/x-javascript' );
    echo $_GET[ 'callback' ] . '({"name":"Morgan"})';
}

Even though the jQuery documentation indicates that the error handler for jsonp calls is never fired, this script works just as I intended. It makes four "unsuccessful" calls to test.php which return 503 errors, and then test() recursively calls itself incrementing x until the ajax call is "successful" and the data is output to the console.

So my test case above works, but my actual code doesn't work, which looks more like the following:

jQuery( document ).ready( function( $ ) {
    var completed = 0;
    var fiftystates; // assume an array of state objects
    var updateState = function( index, state ) {
        var d = index % 5; // for subdomains sub0, sub1, sub2, sub3, sub4
        $.ajax({
            url: 'http://sub' + d + '.mydomain.com/update_state.php',
            data: { state: state.id },
            dataType: 'jsonp',
            crossDomain: true,
            success: function() { 
                completed++; 
                var complete_percent = completed / fiftystates.length * 100;
                $( '#progressbar' ).progressbar( 'value', completed_percent );
            },
            error: function() {
                updateState( index, state );
            }
        }); // end ajax
    }; // end updateState
    $( fiftystates ).each( updateState );
};

As you can see, this loops through 5 different sub-domains which are actually just mirrors of the same domain, but since update_state.php can take up to 30 seconds to complete, this takes a 25 minute process down to less than three minutes. The problem is that the server pounding causes some of the ajax requests to fail with a 503 error. In my test case this was handled with no problem but in my second example, the error handler never seems to get called.

I can't figure out why the test case works as I expect and the second one doesn't. Any ideas?

morphatic
  • 7,677
  • 4
  • 47
  • 61
  • tried changing up to jQuery 1.6.4 with same result – morphatic Oct 07 '11 at 06:09
  • could it be that using the php `header()` to return 503 behaves differently than an "actual" 503? I examined the HTTP headers of both cases and they look identical to me... – morphatic Oct 07 '11 at 16:11
  • In your first example, you increment x each time (x++;) in the error handler. In your second, you do not increment index++; that's the only obvious difference I can see. – Kato Oct 24 '11 at 15:47
  • Also, have you tried your 503 test without the die() command? Could that be preventing additional server headers from getting added that are causing it to utilize success in the second case? – Kato Oct 24 '11 at 15:54
  • Also, shouldn't your header call be like this? header("HTTP/1.0 503 Service Temporarily Unavailabel", true, 503); maybe that's causing them to behave differently? See here for more thoughts: http://stackoverflow.com/questions/2760884/how-do-i-make-php-page-return-a-503-error-or-anything-non-200 (okay, I go now :) ) – Kato Oct 24 '11 at 15:57

4 Answers4

4

should it be in format like this:

$.ajax({
    type: "POST",
    url: 'http://servername/WebService.svc/GetData?callback=?',
    dataType: 'jsonp',
    success: function (data) {
       //do stuff
    },
    error: function (msg, b, c) {
    //alert error
    }
 });
Shawn
  • 184
  • 2
  • 14
  • JSONP cannot be used to make POST requests across domains. jQuery will automatically change this to a GET request. – cesarislaw Feb 11 '14 at 22:35
  • 3
    check jquery website "Note: This handler is not called for cross-domain script and cross-domain JSONP requests." – shereifhawary Apr 20 '14 at 06:40
3

In your test case you change teh value x für each call...

In the other code you're sending the same index value. Which will return the same result, instead of "revolving" through the subdomains...

    error: function() {
        index++;
        updateState( index, state );
    }
blindfold
  • 151
  • 3
  • 1
    The index parameter is automatically incremented by the jQuery.each() function call on the next to last line. Good thought, but I don't think that's the issue. – morphatic Dec 23 '11 at 22:54
  • I understand that the index is changed by .each() function call. Still that doesn't affect the index that is called in the error case. For each state in your array you call the function, which call itself in case of an error... – blindfold Jan 02 '12 at 13:55
3

If by chance you were using IE to test the first case and possibly FF or Chrome to test the second case then that may be the cause. Error and Global callbacks are not called for cross domain JSON/JSONP types as documented by the jQuery.ajax function. However, I have noticed that they do still get called in IE and I think this has something to do with jQuery using the IE XMLHttpRequest to do the calls.

It appears someone has graciously created a plugin that handles errors with JSONP requests available here: http://code.google.com/p/jquery-jsonp/

WhoopP
  • 141
  • 7
1
function AjaxRequest(url, params){

    return $.ajax({
        url:            url,
        data:           params,
        dataType:       'jsonp',

        /* Very important */
        contentType:    'application/json',
    });
}

var test = function(x) {

    AjaxFeed('http://servername/WebService.svc/GetData', {x: x})

    /* Everything worked okay. Hooray */
    .done(function(data){

        console.log(data);
    })

    /* Oops */
    .fail(function(jqXHR, sStatus, oError) {

        console.log(arguments);
    });
}

jQuery(window).load(function() {

    test('test');
}
mAsT3RpEE
  • 1,818
  • 1
  • 17
  • 14