$.ajax()接受一个对象参数,这个对象包含两个方法: success():指定操作成功后的回调函数, error():指定操作失败后的回调函数。
可以看到done()相当于success方法,fail()相当于error方法。采用链式写法以后,代码的可读性大大提高。
注意:$.ajax()操作完成后,如果使用的是低于1.5.0版本的jQuery,返回的是XHR对象,你没法进行链式操作;如果高于1.5.0版本,返回的是deferred对象,可以进行链式操作。
deferred对象的一大好处,就是它允许你自由添加多个回调函数,代码中,除了原来的done()和fail(),在后面又添加了一个done(),运行结果依次弹出“成功了!”、“再执行一个回调函数!”。注这里的回调函数可以添加任意多个,它们按照添加顺序执行。
deferred对象的另一大好处,就是它允许你为多个事件指定一个回调函数,这是传统写法做不到的。这里用到了一个新的方法$.when(),它的意思是,先执行两个操作$.ajax(“demo1.php”)和$.ajax(“demo2.php”),如果都成功了,就运行done()指定的回调函数;否则,就执行fail()指定的回调函数。
deferred对象的最大优点,就是它把这一套回调函数接口,从ajax操作扩展到了所有操作。也就是说,任何一个操作----不管是ajax操作还是本地操作,也不管是异步操作还是同步操作---- 都可以使用deferred对象的各种方法,指定回调函数。
假设有一个很耗时的操作wait,如果我们要为它指定回调函数,应该怎么做?
wait()函数中,dtd是一个deferred对象,resolve()改变deferred对象的状态为“已完成”; 现在,wait()函数返回的是deferred对象,运行代码,结果等待5秒后,弹出“执行完成”,紧接着再弹出“成功了!”
Query规定,deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolve),deferred对象立刻调用done()指定的回调函数;如果执行状态是"已失败",调用fail()指定的回调函数;如果执行状态是"未完成",则继续等待,或者调用progress()指定的回调函数(jQuery1.7版本 添加)。 前面部分的ajax操作,deferred对象会根据返回结果,自动改变自身的执行状态;但是,在wait()函数中,这个执行状态必须手动指定。dtd.resolve()的作用是,将dtd对象的执行状态从"未完成"改为"已完成",从而触发done()方法。 对应的,还有一个reject(),作用是将dtd对象的执行状态从"未完成"改为"已失败",从而触发fail()方法。
运行结果,等待5秒后,弹出“执行完成”,紧接着再弹出“出错了!”
在刚刚的例子中,会存在一个问题,deferred对象的状态可以从wait()函数的外面对其进行改变,像这样,运行结果,立马弹出“成功了!”,等待5秒后,弹出“执行完成”
为了防止执行状态被从外部改变,jQuery提供了deferred.promise()方法。 它的作用是,在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done() 和fail()),屏蔽与改变执行状态有关的方法(比如resolve()和reject()),从而使得执行状态不能被改变。
wait()函数中,dtd.promise()返回的是promise对象,此时,d.resolve()是无效的。 运行结果,等待5秒后,弹出“执行完成”,紧接着再弹出“出错了!”