29
2013
01

多ajax请求的各类解决方案(同步, 队列, cancel请求)

疯狂的ajax,ajax带来很好的用户体验,于是一个稍微注重web系统使用ajax基本成为必然。当传统功能型web项目向用户体验型项目转变时,层出不穷的需求就来了。正如本篇所介绍的就是一个多个AJAX请求的情况下,如何利用jquery来处理几种case。


多个ajax请求同时发送,相互无依赖。

多个ajax请求相互依赖,必须有先后顺序。

多个请求被同时发送,只需要最后一个请求。


第1种case

应用场景: 这个场景很多,一个页面打开是多个区域同时请求后台得到各自的数据,没依赖,没顺序。

处理方案: 直接用jquery的ajax函数。这个用的非常多,这里从略,可看后面的代码中例子。


第2种case

应用场景: 多个ajax请求,需要顺序执行,后一个ajax请求的执行参数是前一个ajax的结果。例如: 用户登录后我们发送一次请求得到用户的应用ID,然后利用应用ID发送一次请求得到具体的应用内容(例子虽然不是太恰当,但基本就是这个意思了)。

处理方法:

   1. 利用ajax参数async设置为false,进行同步操作。(这个方法只适合同域操作,跨域需使用下面两种方法)

   2. 利用ajax嵌套(这个同第1种情况)

   3. 利用队列进行操作


jquery ajax队列操作核心代码:

(function ($) {
    var ajaxRequest = {};
      
    $.ajaxQueue = function (settings) {
        var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
        var _complete = options.complete;
        $.extend(options, {
            complete: function () {
                if (_complete)
                    _complete.apply(this, arguments);
      
                if ($(document).queue(options.className).length > 0) {
                    $(document).dequeue(options.className);
                } else {
                    ajaxRequest[options.className] = false;
                }
            }
        });
      
        $(document).queue(options.className, function () {
            $.ajax(options);
        });
      
        if ($(document).queue(options.className).length == 1 && !ajaxRequest[options.className]) {
            ajaxRequest[options.className] = true;
            $(document).dequeue(options.className);
        }
    };
      
      
})(jQuery);

第3中case

应用场景: 比较典型的是autocomplete控件的操作,这个我们可以使用第2种情况的处理方法,但我们可能只需要最后次按键后返回的结果,这样利用第2种处理方法未免有些浪费。

处理方法: 保留最后一次请求,cancel之前的请求。

(function ($) {
var jqXhr = {};
 $.ajaxSingle = function (settings) {
        var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
    
        if (jqXhr[options.className]) {
            jqXhr[options.className].abort();
        }
    
        jqXhr[options.className] = $.ajax(options);
    };
})(jQuery);


对于这些case都是在多个ajax请求,响应时间不能控制的情况。下面是完整Demo代码。


所有JS代码

(function ($) {
    var jqXhr = {},
        ajaxRequest = {};
    
    $.ajaxQueue = function (settings) {
        var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
        var _complete = options.complete;
        $.extend(options, {
            complete: function () {
                if (_complete)
                    _complete.apply(this, arguments);
    
                if ($(document).queue(options.className).length > 0) {
                    $(document).dequeue(options.className);
                } else {
                    ajaxRequest[options.className] = false;
                }
            }
        });
    
        $(document).queue(options.className, function () {
            $.ajax(options);
        });
    
        if ($(document).queue(options.className).length == 1 && !ajaxRequest[options.className]) {
            ajaxRequest[options.className] = true;
            $(document).dequeue(options.className);
        }
    };
    
    $.ajaxSingle = function (settings) {
        var options = $.extend({ className: 'DEFEARTNAME' }, $.ajaxSettings, settings);
    
        if (jqXhr[options.className]) {
            jqXhr[options.className].abort();
        }
    
        jqXhr[options.className] = $.ajax(options);
    };
    
})(jQuery);
    
var ajaxSleep = (function () {
    var _settings = {
        type: 'GET',
        cache: false,
        success: function (msg) {
            var thtml = $('#txtContainer').html();
            $('#txtContainer').html(thtml + "<br />" + msg);
        }
    };
    return {
        get: function (seconds, mode, isAsync) {
            var mode = mode || 'ajax',
                        isAsync = isAsync || false;
    
            $[mode]($.extend(_settings, {
                url: "ResponsePage.aspx?second=" + seconds,
                async: isAsync,
                className: 'GET'
            }));
        },
        post: function (seconds, mode, isAsync) {
            var mode = mode || 'ajax',
                        isAsync = isAsync || false;
    
            $[mode]($.extend(_settings, {
                type: 'POST',
                url: "PostPage.aspx",
                data: { second: seconds },
                async: isAsync,
                className: 'POST'
            }));
        }
    };
} ());
    
var launch = function (settings) {
    
    $('#txtContainer').html('');
    
    var mode = settings.mode,
                isAsync = settings.isAsync;
    
    ajaxSleep.get(12, mode, isAsync);
    ajaxSleep.get(10, mode, isAsync);
    ajaxSleep.get(8, mode, isAsync);
    
    ajaxSleep.post(6, mode, isAsync);
    ajaxSleep.post(4, mode, isAsync);
    ajaxSleep.post(2, mode, isAsync);
}
    
$(document).ready(function () {
    //第1种case
    $('#btnLaunchAsync').click(function () {
        launch({ isAsync: true });
    });
    
    //第2种case
    $('#btnLaunchSync').click(function () {
        launch({});
    });
    
    //第2种case
    $('#btnLaunchQueue').click(function () {
        launch({ mode: 'ajaxQueue', isAsync: true });
    });
    
    //第3种case
    $('#btnLaunchSingle').click(function () {
        launch({ mode: 'ajaxSingle', isAsync: true });
    });
});


default.html页面

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="js/default.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <input type="button" id="btnLaunchAsync" value="Launch Asynchronous Request" />
    <input type="button" id="btnLaunchSync" value="Launch Synchronous Request" />
    <input type="button" id="btnLaunchQueue" value="Launch Requested Queue" />
    <input type="button" id="btnLaunchSingle" value="Launch Single Request" />
    <div id="txtContainer"></div>
    </form>
</body>
</html>

ASP.NET测试代码设置

//ResponsePage.aspx
protected void Page_Load(object sender, EventArgs e)
        {
            int seconds = int.Parse(Request.QueryString["second"]);
            Thread.Sleep(seconds*1000);
    
            Response.Write("GET: selpt for "+ seconds.ToString() +" sec(s)");
        }
    
//PostPage.aspx
        protected void Page_Load(object sender, EventArgs e)
        {
            int seconds = int.Parse(Request.Form["second"]);
    
            Thread.Sleep(seconds * 1000); 
    
            Response.Write("POST: selpt for " + seconds.ToString() + " sec(s)");
        }

后注: 个人能力有限,如有错误敬请指点。这些只是些根据一些特定情况下的处理,如果一个ajax请求能解决的问题切勿利用两个请求来处理,毕竟需要占用资源。我还是相信没有最好的方案,只有最适合的方案。


« 上一篇下一篇 »

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。