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

  •多个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代码。

  

复制代码 代码如下:

  (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)");

  }

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