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

发布于 2024-12-08 18:06:18 字数 2178 浏览 0 评论 0原文

我构建了一个 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 文档 表明 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 错误。在我的测试用例中,处理没有问题,但在我的第二个示例中,错误处理程序似乎从未被调用。

我不明白为什么测试用例按我的预期工作,而第二个测试用例却没有。有什么想法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

星光不落少年眉 2024-12-15 18:06:18

应该是这样的格式:

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

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
    }
 });
我不是你的备胎 2024-12-15 18:06:18

在您的测试用例中,您每次调用都会更改值x...

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

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

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 );
    }
盛装女皇 2024-12-15 18:06:18

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

看来有人慷慨地创建了一个插件,可以处理此处提供的 JSONP 请求的错误:http://code .google.com/p/jquery-jsonp/

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/

泛泛之交 2024-12-15 18:06:18
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');
}
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');
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文