在Web开发中,异步请求是常见的需求。jQuery提供了强大的工具来处理异步请求,其中Deferred对象和Promise接口是处理异步请求的关键。Deferred对象可以注册回调函数,根据异步操作的成功或失败来执行。Promise接口则提供了一种方式来处理异步操作的结果。本文将介绍如何使用这些工具来处理多个Ajax请求。
首先,来看一个ASP.NET Web API的示例,它提供了两个接受Ajax调用的方法。一个方法返回一个字符串数组,另一个方法根据传入的ID返回一个字符串。
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
string s = "Id is " + Convert.ToString(id);
return s;
}
}
使用jQuery的$.ajax
函数可以发起一个Ajax请求。这里是一个简单的示例,它在请求成功时弹出数组的第一个元素,在请求失败时弹出错误信息。
$.ajax({
url: 'api/values',
dataType: 'json',
type: 'GET',
success: function(data) {
alert(data[0]);
},
error: function() {
alert('Error!');
}
});
jQuery的Deferred对象可以注册回调函数,这些回调函数会在Deferred对象被解决(resolved)或拒绝(rejected)时执行。下面是一个Deferred对象的示例。
// 创建一个Deferred对象
var def1 = $.Deferred();
// 添加一个在Deferred对象被解决时调用的函数
def1.done(function(data) {
alert(data);
});
// 解决Deferred对象
def1.resolve('Resolved!');
// 创建另一个Deferred对象
var def2 = $.Deferred();
// 添加一个在Deferred对象被拒绝时调用的函数
def2.fail(function(data) {
alert(data);
});
// 拒绝Deferred对象
def2.reject('Rejected!');
Deferred对象可以被链式调用。下面是一个Deferred对象链的示例。
var def = $.Deferred();
def.done(function(data) {
alert(data);
}).fail(function(data) {
alert(data);
});
// 拒绝Deferred对象
def.reject('Rejected!');
Deferred对象有一个promise
方法,它返回一个Promise对象。Promise对象暴露了Deferred对象的一部分方法,以防止其状态被手动改变。这意味着,不能手动解决或拒绝Deferred对象。Promise对象暴露了以下Deferred方法:then
, done
, fail
, always
, pipe
, progress
, state
和promise
。它不暴露以下Deferred方法:resolve
, reject
, notify
, resolveWith
, rejectWith
和notifyWith
。
jQuery的$.ajax
函数返回一个jqXHR对象。关于这个jqXHR对象有两个重要事实。首先,jqXHR对象是XMLHTTPRequest对象的超集。例如,可以通过jqXHR对象的readyState
属性查询XMLHTTPRequest的状态。如果其readyState
为4,则表示Ajax请求已完成。其次,jqXHR对象实现了Promise接口,并暴露了所有Promise方法。基本上,可以将jqXHR对象视为Promise对象。例如,可以使用done
方法作为jqXHR对象的成功回调函数。
$(document).ready(function() {
var j1 = $.ajax({
url: 'api/values',
dataType: 'json',
type: 'GET'
});
var j2 = $.ajax({
url: 'api/values',
dataType: 'json',
data: { id: 5 },
type: 'GET'
});
$.when(j1, j2).then(function(a1, a2) {
alert('Both j1 and j2 succeeded!');
}, function(jqXHR, textStatus, errorThrown) {
var x1 = j1;
var x2 = j2;
if (x1.readyState != 4) {
x1.abort();
}
if (x2.readyState != 4) {
x2.abort();
}
alert('Either j1 or j2 failed!');
});
});