Deferred 和 PromiseES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不過它們的作用可以簡單的用兩句話來描述Deffered 觸發 resolve 或 rejectPromise 中申明 resolve 或 reject 後應該做什麼(回撥)在 jQuery 中var deferred = $.Deferred(); var promise = deferred.promise();在 ES6 中var deferred = Promise.defer(); var promise= defered.promise;MDN 宣佈 Deferred 在 Gecko 30 中被申明為過期,不應該再使用,而應該用 new Promise() 來代替。關於 new Promise() 將在後面說明。jQuery 的 Deferred/PromisejQuery 中最常用的 Promise 物件是 $.ajax() 返回的,最常用的方法不是 then ,而是 done 、 fail 和 always 。除了 $.ajax() 外,jQuery 也提供了 $.get() 、 $.post() 和 $.getJSON() 等簡化 Ajax 呼叫,它們返回的和 $.ajax() 的返回值一樣,是個 Promise 物件。實際上 $.ajax() 返回的是一個 jqXHR 物件 。但 jqXHR 實現了 jQuery 的 Promise 介面,所以也是一個 Promise 物件。done() 、 fail() 和 always()done() 新增 deferred.resolve() 的回撥, fail() 新增 deferred.reject() 的回撥。所以在 Ajax 呼叫成功的情況下執行 done() 新增的回撥,呼叫失敗時執行 fail() 新增的回撥。但不管成功與否,都會執行 always() 新增的回撥。這裡 done() 、 fail() 和 always() 都是以類似事件的方式添加回調,也就意味著,不管執行多次次 done() 、 fail() 或 always() ,它們新增的若干回撥都會在符合的條件下依次執行。一般情況下會這樣執行 Ajax// 禁用按鈕以避免重複提交 $("#theButton").prop({ disabled: true }); // 呼叫 Ajax 提交資料,假設返回的是 JSON 資料 var jqxhr = $.ajax("do/example", { type: "post", dataType: "json", data: getFormData() }); jqxhr.done(function(jsonObject) { // Ajax 呼叫成功 console.log("success with data", jsonObject); }).fail(function() { // Ajax 呼叫失敗 console.log("failed") }).always(function() { // 不管成功與否,都會執行,取消按鈕的禁用狀態 $("#theButton").prop({ disabled: false }); });上面是最普通最常用的用法,但是在一個專案中總是這麼寫 Ajax,有點累,稍微約定一下再封裝一下就使用起來就會便捷得多。首先,假設我們定義返回的 JSON 是這樣的格式:{ "code": "int, 0 表示成功,其它值表示出錯", "message": "string, 附加的訊息,可選", "data": "object,附加的資料,可選 }然後為專案公共類 app 定義一個 ajax 方法app.ajax = function(button, url, data) { if (button) { button.prop("disabled", true); } return $.ajax(url, { type: "post", dataType: "json", data: data }).done(function(json) [ if (json.code !== 0) { showError(json.message || "操作發生錯誤"); } }).fail(function() { showError("伺服器錯誤,請稍後再試"); }).always(function() { if (button) { button.prop("disabled", false); } }); }; // 呼叫 app.ajax("do/example", getFormData().done(function(json) { if (json.code === 0) { // 只需要處理正確的情況啦 } });
Deferred 和 PromiseES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不過它們的作用可以簡單的用兩句話來描述Deffered 觸發 resolve 或 rejectPromise 中申明 resolve 或 reject 後應該做什麼(回撥)在 jQuery 中var deferred = $.Deferred(); var promise = deferred.promise();在 ES6 中var deferred = Promise.defer(); var promise= defered.promise;MDN 宣佈 Deferred 在 Gecko 30 中被申明為過期,不應該再使用,而應該用 new Promise() 來代替。關於 new Promise() 將在後面說明。jQuery 的 Deferred/PromisejQuery 中最常用的 Promise 物件是 $.ajax() 返回的,最常用的方法不是 then ,而是 done 、 fail 和 always 。除了 $.ajax() 外,jQuery 也提供了 $.get() 、 $.post() 和 $.getJSON() 等簡化 Ajax 呼叫,它們返回的和 $.ajax() 的返回值一樣,是個 Promise 物件。實際上 $.ajax() 返回的是一個 jqXHR 物件 。但 jqXHR 實現了 jQuery 的 Promise 介面,所以也是一個 Promise 物件。done() 、 fail() 和 always()done() 新增 deferred.resolve() 的回撥, fail() 新增 deferred.reject() 的回撥。所以在 Ajax 呼叫成功的情況下執行 done() 新增的回撥,呼叫失敗時執行 fail() 新增的回撥。但不管成功與否,都會執行 always() 新增的回撥。這裡 done() 、 fail() 和 always() 都是以類似事件的方式添加回調,也就意味著,不管執行多次次 done() 、 fail() 或 always() ,它們新增的若干回撥都會在符合的條件下依次執行。一般情況下會這樣執行 Ajax// 禁用按鈕以避免重複提交 $("#theButton").prop({ disabled: true }); // 呼叫 Ajax 提交資料,假設返回的是 JSON 資料 var jqxhr = $.ajax("do/example", { type: "post", dataType: "json", data: getFormData() }); jqxhr.done(function(jsonObject) { // Ajax 呼叫成功 console.log("success with data", jsonObject); }).fail(function() { // Ajax 呼叫失敗 console.log("failed") }).always(function() { // 不管成功與否,都會執行,取消按鈕的禁用狀態 $("#theButton").prop({ disabled: false }); });上面是最普通最常用的用法,但是在一個專案中總是這麼寫 Ajax,有點累,稍微約定一下再封裝一下就使用起來就會便捷得多。首先,假設我們定義返回的 JSON 是這樣的格式:{ "code": "int, 0 表示成功,其它值表示出錯", "message": "string, 附加的訊息,可選", "data": "object,附加的資料,可選 }然後為專案公共類 app 定義一個 ajax 方法app.ajax = function(button, url, data) { if (button) { button.prop("disabled", true); } return $.ajax(url, { type: "post", dataType: "json", data: data }).done(function(json) [ if (json.code !== 0) { showError(json.message || "操作發生錯誤"); } }).fail(function() { showError("伺服器錯誤,請稍後再試"); }).always(function() { if (button) { button.prop("disabled", false); } }); }; // 呼叫 app.ajax("do/example", getFormData().done(function(json) { if (json.code === 0) { // 只需要處理正確的情況啦 } });