Promise的介紹和優點
es6中的promise時異步編程的一種方案. 從語法上來講, promise是一個對象, 它可以獲取異步操作的消息
promise對象, 可以將異步操作以同步的流程表達出來
好處:
可以很好的解決回調地獄問題 (避免了層層嵌套的回調函數)
語法非常簡潔. promise對象提供簡介的api, 使得控制異步操作更加容易
Promise的基本用法
1 new實例化一個promise對象, promise的構造函數中傳遞一個參數, 是一個函數, 該函數用於處理異步任務
2 傳入兩個參數: resolve和reject, 分別代表異步執行成功後的回調函數和失敗後的回調函數
3 通過promise.then()處理返回結構
實例
// 第一步:model層的接口封裝
const promise = new Promise((resolve, reject) => {
// 這裏做異步任務(比如ajax 請求接口。這裏暫時用定時器代替)
setTimeout(function() {
var data = { retCode: 0, msg: 'qianguyihao' }; // 接口返回的數據
if (data.retCode == 0) {
// 接口請求成功時調用
resolve(data);
} else {
// 接口請求失敗時調用
reject({ retCode: -1, msg: 'network error' });
}
}, 100);
});
// 第二步:業務層的接口調用。這裏的 data 就是 從 resolve 和 reject 傳過來的,也就是從接口拿到的數據
promise.then(data => {
// 從 resolve 獲取正常結果
console.log(data);
}).catch(data => {
// 從 reject 獲取異常結果
console.log(data);
});
Promise對象的3個狀態
初始化狀態(等待狀態): pending
成功狀態: fullfilled
失敗狀態: rejected
(1)當new Promise()執行之後,promise對象的狀態會被初始化為pending,這個狀態是初始化狀態。new Promise()這行代碼,括號裏的內容是同步執行的。括號裏定義一個function,function有兩個參數:resolve和reject。如下:
- 如果請求成功了,則執行resolve(),此時,promise的狀態會被自動修改為fullfilled。
- 如果請求失敗了,則執行reject(),此時,promise的狀態會被自動修改為rejected
(2)promise.then()方法,括號裏面有兩個參數,分別代表兩個函數 function1 和 function2:
- 如果promise的狀態為fullfilled(意思是:如果請求成功),則執行function1裏的內容
- 如果promise的狀態為rejected(意思是,如果請求失敗),則執行function2裏的內容
Promise處理多次ajax請求(鏈式調用)
promise可以把原本的多層嵌套調用改為鏈式調用
/*
基於Promise發送Ajax請求
*/
function queryData(url) {
var promise = new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 處理正常情況
resolve(xhr.responseText); // xhr.responseText 是從接口拿到的數據
} else {
// 處理異常情況
reject('接口請求失敗');
}
};
xhr.responseType = 'json'; // 設置返回的數據類型
xhr.open('get', url);
xhr.send(null); // 請求接口
});
return promise;
}
// 發送多個ajax請求並且保證順序
queryData('http://localhost:3000/api1')
.then(
data1 => {
console.log(JSON.stringify(data1));
// 請求完接口1後,繼續請求接口2
return queryData('http://localhost:3000/api2');
},
error1 => {
console.log(error1);
}
)
.then(
data2 => {
console.log(JSON.stringify(data2));
// 請求完接口2後,繼續請求接口3
return queryData('http://localhost:3000/api3');
},
error2 => {
console.log(error2);
}
)
.then(
data3 => {
// 獲取接口3返回的數據
console.log(JSON.stringify(data3));
},
error3 => {
console.log(error3);
}
);
Promise的常用API: 實例方法
promise.then(): 獲取異步任務的正常結果
promise.catch(): 獲取異步任務的異步結果
promise.finaly(): 異步任務無論成功與否, 都會執行
queryData()
.then(data => {
// 從 resolve 獲取正常結果
console.log('接口請求成功時,走這裏');
console.log(data);
})
.catch(data => {
// 從 reject 獲取異常結果
console.log('接口請求失敗時,走這裏');
console.log(data);
})
.finally(() => {
console.log('無論接口請求成功與否,都會走這裏');
});
queryData()
.then(
data => {
// 從 resolve 獲取正常結果
console.log('接口請求成功時,走這裏');
console.log(data);
},
data => {
// 從 reject 獲取異常結果
console.log('接口請求失敗時,走這裏');
console.log(data);
}
)
.finally(() => {
console.log('無論接口請求成功與否,都會走這裏');
});
Promise的常用API: 對象方法
promise.all(): 併發處理多個異步任務, 所有任務都執行成功, 才能得到結果.
promise.race(): 併發處理多個異步處理, 只要一個任務執行成功, 就能得到結果
/*
封裝 Promise 接口調用
*/
function queryData(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 處理正常結果
resolve(xhr.responseText);
} else {
// 處理異常結果
reject('服務器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
var promise1 = queryData('http://localhost:3000/a1');
var promise2 = queryData('http://localhost:3000/a2');
var promise3 = queryData('http://localhost:3000/a3');
Promise.all([promise1, promise2, promise3]).then(result => {
console.log(result);
});
/*
封裝 Promise 接口調用
*/
function queryData(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 處理正常結果
resolve(xhr.responseText);
} else {
// 處理異常結果
reject('服務器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
var promise1 = queryData('http://localhost:3000/a1');
var promise2 = queryData('http://localhost:3000/a2');
var promise3 = queryData('http://localhost:3000/a3');
Promise.race([promise1, promise2, promise3]).then(result => {
console.log(result);
});