狀態機:抽象的計算模型,根據特定的條件或者信號切換不同的狀態
一、Promise 是什么?
簡單來說,Promise 就是一個“承諾對象”。在ES6 里,有些代碼執行起來需要點時間,比如加載文件、等待網絡請求或者設置定時器,這些代碼被叫做“生產代碼”;而另外一些代碼得等著生產代碼出結果才能執行,這就是“消費代碼”。Promise 就像一座橋,把生產代碼和消費代碼連接起來。
它本身包含了生產代碼,還會調用消費代碼。Promise 有三種狀態:
- pending(進行中):就像任務還在執行中,結果還沒出來。
- fulfilled(已完成):任務成功完成,有了一個結果值。
- rejected(已拒絕):任務出錯了,得到一個錯誤對象。
不過呢,咱們不能直接去訪問 Promise 的狀態(state)和結果(result),得通過它的方法來處理。
二、Promise 怎么用?
(一)基本語法
創建一個 Promise 得用 new Promise()
,里面傳一個函數,這個函數有兩個參數,myResolve
和 myReject
:
let promise = new Promise(function(resolve, reject) {// 生產代碼if (/* 條件滿足,任務成功 */) {resolve("成功啦!"); // 成功時調用} else {reject("出錯咯!"); // 失敗時調用}
});
(二)處理結果
用 .then()
來處理 Promise 的結果,它可以接收兩個函數:
- 第一個函數是任務成功時執行的。
- 第二個函數是任務失敗時執行的。這兩個函數都是可選的,你可以只寫成功的或者只寫失敗的處理函數。
promise.then(function(value) { /* 成功了咋處理 */ },function(error) { /* 失敗了咋處理 */ }
);
(三)舉個栗子
比如,我們用 Promise 來模擬一個 3 秒后的定時器:
function showMessage(some) {document.getElementById("demo").innerHTML = some;
}let promise = new Promise(function(resolve, reject) {let x = 0;if (x == 0) {resolve("OK"); // x 等于 0,任務成功} else {reject("Error"); // x 不等于 0,任務失敗}
});promise.then(function(value) { showMessage(value); }, // 成功時顯示 "OK"function(error) { showMessage(error); } // 失敗時顯示 "Error"
);
再比如,用 Promise 來處理文件請求:
let promise = new Promise(function(resolve, reject) {let req = new XMLHttpRequest();req.open('GET', "xxx.html");req.onload = function() {if (req.status == 200) {resolve(req.response); // 請求成功,返回文件內容} else {reject("File not Found"); // 請求失敗,返回錯誤信息}};req.send();
});promise.then(function(value) { showMessage(value); }, // 成功時顯示文件內容function(error) { showMessage(error); } // 失敗時顯示錯誤信息
);
三、什么時候該用 Promise?
當你遇到以下情況時,就可以考慮用 Promise 啦:
- 需要處理異步操作:像定時器
setTimeout
、網絡請求(AJAX)、文件讀取這些操作,都是異步的,不會阻塞代碼執行,這時候用 Promise 能讓代碼更清晰。 - 避免回調地獄:如果有多個異步操作需要按順序執行,用傳統的回調函數可能會寫成嵌套的形式,代碼看起來像個“地獄”,而 Promise 可以通過鏈式調用讓代碼更有條理。
- 統一處理成功和失敗:不管異步操作是成功還是失敗,都可以通過
.then()
或者.catch()
來統一處理結果,讓代碼更簡潔。
四、Promise 原理是
Promise 的核心原理其實就是狀態機:
- 一開始,Promise 處于
pending
狀態,這時候生產代碼在執行。 - 當生產代碼執行成功,就會調用
myResolve()
,Promise 狀態變成fulfilled
,然后執行.then()
里的成功回調函數。 - 要是生產代碼執行出錯,就會調用
myReject()
,Promise 狀態變成rejected
,接著執行.then()
里的失敗回調函數。
而且,Promise 的狀態一旦改變,就不會再變了。也就是說,一旦變成 fulfilled
或者 rejected
,就定格在這個狀態了,這樣可以避免重復處理結果。
Promise 是 ES6(ECMAScript 2015)引入的特性,現在主流的瀏覽器基本都支持,比如 Chrome 33 及以上、Firefox 29 及以上等等,所以不用擔心兼容性問題,可以放心用起來啦!