ES6 Promise物件--將非同步程式碼像同步程式碼那些書寫
ES6 Promise物件--將非同步程式碼像同步程式碼那些書寫
部落格說明
文章所涉及的資料來自網際網路整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯絡本人刪除,謝謝!
簡介
從語法上說,Promise 是一個物件,從它可以獲取非同步操作的訊息。Promise 提供統一的 API,各種非同步操作都可以用同樣的方法進行處理。通俗來說,Promise是一個容器,裡面儲存著非同步操作的結果。
特點
物件的狀態不受外界影響
Promise
物件有三種狀態:pending
(進行中)、fulfilled
(已成功)和rejected
(已失敗)。
只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。
一旦狀態改變,就不會再變,任何時候都可以得到這個結果
Promise
物件的狀態改變,只有兩種可能:從pending
變為fulfilled
和從pending
變為rejected
。只要這兩種情況發生,狀態就凝固了,不會再變了,並且會一直保持這個結果,這時就稱為 resolved(已定型)。
優點與缺點
優點
1、Promise
物件可以將非同步操作以同步操作的流程表達出來,用同步的方式寫非同步的程式碼,避免了層層巢狀的回撥函式。
2、Promise
物件提供統一的介面,使得控制非同步操作更加容易。
缺點
1、無法取消Promise
,一旦新建它就會立即執行,無法中途取消。
2、如果不設定回撥函式,Promise
3、第三,當處於pending
狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
案例
Promise例項
Promise
建構函式接受一個函式作為引數,該函式的兩個引數分別是resolve
和reject
。注意這兩個是兩個函式。
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 非同步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
resolve
函式的作用是,將Promise
reject
函式的作用是,將Promise
物件的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在非同步操作失敗時呼叫,並將非同步操作報出的錯誤,作為引數傳遞出去。
Promise執行順序
Promise
新建後就會立即執行。
let promise = new Promise(function(resolve, reject) {
console.log('11');
resolve();
});
promise.then(function() {
console.log('22');
});
console.log('33');
// 11
// 33
// 22
Promise 新建後立即執行,所以首先輸出的是11
。then
方法指定的回撥函式屬於非同步函式,在當前指令碼所有同步任務執行完才會執行,所以輸出33
,22
最後輸出。
非同步載入圖片案例
使用Promise
包裝了一個圖片載入的非同步操作。如果載入成功,就呼叫resolve
方法,否則就呼叫reject
方法。
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
const image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
Promise物件實現的 Ajax
在getTest
函式中對 XMLHttpRequest 物件進行了封裝,傳送一個 HTTP 請求,得到一個Promise
物件。
const getTest = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
// 呼叫案例
getTest("/test.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error(error);
});
Promise錯誤處理
如果 Promise 狀態已經變成resolved
,再丟擲錯誤是無效的。因為 Promise 的狀態一旦改變,就永久保持該狀態,不會再變了。
Promise 物件的錯誤具有冒泡
性質,會一直向後傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch
語句捕獲。
const promise = new Promise(function(resolve, reject) {
resolve('ok');
throw new Error('test');
});
promise
.then(function(value) { console.log(value) })
.catch(function(error) { console.log(error) });
// ok
感謝
萬能的網路
阮一峰的es6語法教程