jQuery - Deferred
1. 初始化:var deferred=$.Deferred(); 参考此文章;
2. Deferred对象的三种动作是resolve, reject, 和 notify,分别对应内部事件done, fail, 和 progress; 具体使用时,定义done()的操作,然后使用对应的resolve()来进行触发;
3. deferred.always();函数只会在调用resolve()和reject()时运行,在notify()时不会运行,而且如果想要always()中的操作在done和fail之后执行,需要将定义always()动作的语句写在done()和fail()事件之后;
4. $.when()为多个操作指定统一的回调函数,可确保多个操作都完成后才进行回调函数中的操作;
如示例中所示,只有当deferred1和deferred2都执行了resolve()动作(即 都调用了done事件)后,success3函数才会执行;
function succeed1(){ alert("Success1!"); } function succeed2(){ alert("Success2!"); } function fail2(){ alert("failed2"); } function succeed3(){ alert("All Success!"); } var deferred1=$.Deferred(); var deferred2=$.Deferred(); deferred1.done(succeed1); deferred2.done(succeed2); deferred2.fail(fail2); $.when(deferred1, deferred2).done(succeed3); setTimeout(function(){ deferred1.resolve(); deferred2.reject(); }, 2000);
5. deferred.promise()返回的对象是一个只能done/fail/progress,不能resolve/reject/notify;即只能调用callbacks.add事件,没有callbacks.fire事件;返回的对象是正统Deferred对象的阉割版,只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。
如下例所示,最后一句的resolve()方法不会被执行,如果直接返回的是deferred对象,则最后一句resolve()会被执行,则造成在wait()函数尚未执行时就先执行了deferred对象的done事件;
var wait = function(){ var dtd = $.Deferred(); // 新建一个Deferred对象 dtd.done(function(){ alert("dtd Done!"); }); dtd.fail(function(){ alert("dtd Fail"); }); var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变Deferred对象的执行状态 alert("a");//check whether resolve() is ran }; setTimeout(tasks,2000); return dtd.promise(); }; var dtdp=wait(); $.when(dtdp) .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); }); dtdp.resolve();
6. 如果使用1.5.0以上的jQuery,$.ajax()返回的就是deferred对象可以直接使用deferred对象的事件,比如done, fail,如下所示:
$.ajax("/echo/html/") .done(function(){ alert("哈哈,成功了!"); }) .fail(function(){ alert("出错啦!"); });
7. $.Deferred可以接受一个函数名(注意,是函数名)作为参数,$.Deferred()所生成的deferred对象将作为这个函数的默认参数;
var wait = function(dtd){ var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变Deferred对象的执行状态 }; setTimeout(tasks,5000); return dtd.promise(); }; $.Deferred(wait)
.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
8. deferred.promise()也可以接受一个函数名,用以在此函数上部署Deferred接口,使其具有Deferred对象的事件,比如done, fail.
var dtd = $.Deferred(); // 生成Deferred对象 var wait = function(dtd){ var tasks = function(){ alert("执行完毕!"); dtd.resolve(); // 改变Deferred对象的执行状态 }; setTimeout(tasks,5000); }; dtd.promise(wait); //关键步骤 wait.done(function(){ alert("哈哈,成功了!"); }).fail(function(){ alert("出错啦!"); }); wait(dtd);
9. deferred.resolve()也可以包含参数,这些参数会被传递给所有绑定在then()和done()中的doneCallbacks函数;类似的,deferred.reject()也可以包含参数,这些参数会被传递给所有绑定在then()和fail()中的failCallbacks函数;deferred.notify()也可以半酣参数,这些参数会被传递给所有绑定在then()和progress()中的Callbacks函数;
function succeed2(params){ alert("Success2!"+params); } function fail2(params){ alert("failed2"+params); } var deferred2=$.Deferred(); deferred2.done(succeed2); deferred2.fail(fail2); setTimeout(function(){ //deferred2.resolve("Resolved"); deferred2.reject("Rejected"); }, 2000);
10. deferred.then()方法的参数顺序是确定的: doneFilter, failFilter, 和progressFilter,但参数的数量是不定的(即,可以只有doneFilter,也可以有doneFilter和failFilter),而且可以为doneFilter设置多个函数,如下例:
$.ajax({url: "/ServerResource.txt"}).then([successFunction1, successFunction2, successFunction3], [errorFunction1, errorFunction2]); //same as var jqxhr = $.ajax({ url: "/ServerResource.txt" }); jqxhr.done(successFunction1); jqxhr.done(successFunction2); jqxhr.done(successFunction3); jqxhr.fail(errorFunction1); jqxhr.fail(errorFunction2);
11.