开发者

jQuery - AJAX request using both native XHR and flXHR (Flash) fallback - how to minimize code duplication?

I need to retrieve data via cross-domain XMLHttpRequest. To make this work in (almost) all browsers, I use native XHR first and, if that fails, flXHR.

The (working) code I currently have for this is as follows:

jQuery.support.cors = true; // must set this for IE to work

$.ajax({
    url: 'http://site.com/dataToGet', 
    transport : 'xhr',
    success: function(data) {
        console.log('Got data via XHR');
        doStuff(data);
    },
    error: function(xhr, textStatus, error) {
        console.log('Error in xhr:', error.message);
        console.log('Trying flXHR...');
        $.ajax({
            url: 'http://site.com/dataToGet',
            transport : 'flXHRproxy',
            success: function (data) {
                console.log('Got data via f开发者_Go百科lXHR');
                doStuff(data);
            },
            error: function (xhr, textStatus, error) {
                console.log('Error in flXHR:', error.message);
                console.log('Both methods failed, data not retrieved.');
            }
        });
    }
});

This feels like a lot of code duplication to me, especially in the success handlers. Is there a more efficient way to do this? I'd really prefer to make one $.ajax call that would try both transports in turn, instead of having to use the error handler to make the call a second time. It's not too bad in this example, but rapidly gets more complicated if the success handler is longer or if the success handler has to itself issue another $.ajax call.


I've created a jquery-specific and slimmed-down fork of flxhr that simplifies your code sample above. You can see an example of usage in the "Usage" section in the README.

https://github.com/b9chris/flxhr-jquery-packed

In particular, you don't want to waste time waiting for a standard CORS request to fail. It's easy to determine whether flxhr is necessary by testing $.support.cors upfront (no need to override it). Then just use flxhr explicitly where necessary.


Why don't you just wrap this in a function by itself? That's after all, how you end up reusing code. You can even pass functions as arguments to make sure that you don't have to repeat this code more than once.

To me this is pretty straight forward but maybe I've misunderstood.

function xhr(success) {
    $.ajax({ 
        success: success, 
        error: function() { 
            $.ajax({ success: success }) 
        } 
    });
}

Then just pass the success handler once

xhr(function(data){/*magic*/});

Or if you wanna basically avoid redundant configuration of the ajax call use the first object as a template, like this:

function xhr(success) {
    var ajaxParams = { success: success };
    ajaxParams.error = function() { 
        $.ajax($.extend(ajaxParams, { transport: 'xhr' })); 
    }
    $.ajax(ajaxParams);
}

I simplified the whole thing a bit, but I hope you get the point.

Edit

Reading that last bit, maybe this will give you some ideas... it's a variation of that last snippet.

function xhr(success) {
    var ajaxParams = { success: success };
    ajaxParams.error = function() { 
        var newParams = $.extend(ajaxParams, { transport: 'xhr' });
        newParams.success = function() {
            // do something
            // arguments is a special array, even if no parameters were
            // defined in any arguments where passed they will be found
            // in the order they were passed in the arguments array
            // this makes it possible to forward the call to another 
            // function
            success.apply(this, arguments); 
        }
        $.ajax(newParams); 
    }
    $.ajax(ajaxParams);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜