1. 程式人生 > >多ajax請求的各類解決方案(同步, 佇列, cancel請求)

多ajax請求的各類解決方案(同步, 佇列, cancel請求)

ajax帶來很好的使用者體驗,於是一個稍微注重web系統使用ajax基本成為必然。當傳統功能型web專案向用戶體驗型專案轉變時,層出不窮的需求就來了。正如本篇所介紹的就是一個多個AJAX請求的情況下,如何利用jquery來處理幾種case

  1. 多個ajax請求同時傳送,相互無依賴。
  2. 多個ajax請求相互依賴,必須有先後順序。
  3. 多個請求被同時傳送,只需要最後一個請求。

第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程式碼。

(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> 

PostPage.aspx & ResponsePage.aspx

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