处理跨域jsonp调用的jQuery.ajax错误

时间:2011-10-07 05:28:45

标签: jquery ajax error-handling cross-domain jsonp

我构建了一个ajax调用(jQuery 1.6.2)的测试用例,看起来像:

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 );
});

相应的test.php文件如下所示:

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"})';
}

即使jQuery documentation表示永远不会触发jsonp调用的错误处理程序,此脚本也可以正常工作。它对test.php进行四次“不成功”调用,返回503错误,然后test()递归调用自身递增x,直到ajax调用“成功”并将数据输出到控制台。

所以上面的测试用例有效,但我的实际代码不起作用,看起来更像是:

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 );
};

正如您所看到的,这会循环遍历5个不同的子域,这些子域实际上只是同一个域的镜像,但由于update_state.php最多需要30秒才能完成,因此需要25分钟的时间才能完成三分钟。问题是服务器冲击导致一些ajax请求失败并出现503错误。在我的测试用例中,这没有问题,但在我的第二个例子中,似乎永远不会调用错误处理程序。

我无法弄清楚为什么测试用例会像我预期的那样工作,而第二个却没有。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

应该是这样的格式:

$.ajax({
    type: "POST",
    url: 'http://servername/WebService.svc/GetData?callback=?',
    dataType: 'jsonp',
    success: function (data) {
       //do stuff
    },
    error: function (msg, b, c) {
    //alert error
    }
 });

答案 1 :(得分:3)

在您的测试用例中,您可以在每次调用时更改值x ...

在其他代码中,您发送的索引值相同。这将返回相同的结果,而不是通过子域“旋转”......

    error: function() {
        index++;
        updateState( index, state );
    }

答案 2 :(得分:3)

如果您偶然使用IE测试第一种情况,可能使用FF或Chrome来测试第二种情况,那可能就是原因。对于jQuery.ajax函数记录的跨域JSON / JSONP类型,不会调用错误和全局回调。但是,我注意到它们仍然在IE中被调用,我认为这与使用IE XMLHttpRequest进行调用的jQuery有关。

似乎有人慷慨地创建了一个插件来处理JSONP请求中的错误:http://code.google.com/p/jquery-jsonp/

答案 3 :(得分: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');
}