1. Deferred物件有resolve和reject方法,可以直接修改狀態
jquery用Deferred實現了Promise規範,Deferred與ES6 Promise的最大區別是:
Deferred物件有resolve()和reject()方法,可以直接隨時修改該物件的狀態。
比如:
var def = $.Deferred(); setTimeout(function(){ //... def.resolve(data); }); //可用直接用: def.resolve('...') //修改其狀態,干擾了真正的非同步流程的觸發。
2. jquery的Promise物件是一個受限的Deferred物件,即沒有resolve和reject方法的物件
通過deferred.promsie()可以返回一個jquery版本的promise物件,其實就是一個去除了resolve和reject方法的deferred物件,
目的是防止意外的修改了promise物件的狀態,影響真正的非同步操作
3. Deferred物件的then方法的進化
// version added: 1.5, removed: 1.8 deferred.then( doneCallbacks, failCallbacks ) // version added: 1.7, removed: 1.8 deferred.then( doneCallbacks, failCallbacks [, progressCallbacks ] ) // version added: 1.8 deferred.then( doneFilter [, failFilter ] [, progressFilter ] ) //catch是then( null, fn )的別名 deferred.catch(failFilter)
deferred物件的then方法中的回撥,在jquery1.8之前是不會修改傳遞資料的,在1.8之後開始變為filter,與ES6 Promise的then一致,
會修改傳遞的資料。
deferred的done和fail方法也是callback方法,不會修改傳遞的資料
deferred.done( doneCallbacks [, doneCallbacks ] )
deferred.fail( failCallbacks [, failCallbacks ] )
4. 用jquery Deferred實現公共的ajax
//done,fail實現,不能直接返回$.ajax,只能返回外部的deferred物件 app.ajax = function(button, url, data) { if (button) { button.prop("disabled", true); } var deferred = $.Deferred(); $.ajax(url, { type: "post", dataType: "json", data: data }).done(function(json) [ if (json.code !== 0) { showError(json.message || "操作發生錯誤"); deferred.reject(); } else { deferred.resolve(json); } }).fail(function() { showError("伺服器錯誤,請稍後再試"); deferred.reject(); }).always(function() { if (button) { button.prop("disabled", false); } }); return deferred.promise(); }; //then實現,可以返回$.ajax,因為then會返回內部的新的Promise,將值傳遞 app.ajax = function(button, url, data) { if (button) { button.prop("disabled", true); } return $.ajax(url, { type: "post", dataType: "json", data: data }).then(function(json) { if (json.code !== 0) { showError(json.message || "操作發生錯誤"); //不必關心promise物件是哪個,只需要能將資料傳遞下去就行 return $.Deferred().reject().promise(); } else { return $.Deferred().resolve(json).promise(); } }, function() { showError("伺服器錯誤,請稍後再試"); return $.Deferred().reject().promise(); }).always(function() { if (button) { button.prop("disabled", false); } }); }; // 呼叫 app.ajax("do/example", getFormData()).done(function(json) { // json.code === 0 總是成立 // 正常處理 json.data 就好 });
參考:https://www.w3cschool.cn/ivmkf/ivmkf-tkpq2518.html
https://www.cnblogs.com/lvdabao/p/jquery-deferred.html