JavaScript的執行環境是單線程。
所謂單線程,是指JS引擎中負責解釋和執行JavaScript代碼的線程只有一個,也就是一次只能完成一項任務,這個任務執行完後才能執行下一個,它會「阻塞」其他任務。這個任務可稱爲主線程。
異步模式可以一起執行多個任務。
常見的異步模式有以下幾種:
-
定時器
-
接口調用
-
事件函數
今天這篇文章,我們重點講一下接口調用。接口調用裏,重點講一下Promise。
接口調用的方式
js 中常見的接口調用方式,有以下幾種:
- 原生ajax
- 基於jQuery的ajax
- Fetch
- Promise
- axios
多次異步調用的依賴分析
-
多次異步調用的結果,順序可能不同步。
-
異步調用的結果如果存在依賴,則需要嵌套。
在ES5中,當進行多層嵌套回調時,會導致代碼層次過多,很難進行維護和二次開發;而且會導致回調地獄的問題。ES6中的Promise 就可以解決這兩個問題。
Promise 概述
Promise的介紹和優點
ES6中的Promise 是異步編程的一種方案。從語法上講,Promise 是一個對象,它可以獲取異步操作的消息。
Promise對象, 可以將異步操作以同步的流程表達出來。使用 Promise 主要有以下好處:
-
可以很好地解決回調地獄的問題(避免了層層嵌套的回調函數)。
-
語法非常簡潔。Promise 對象提供了簡潔的API,使得控制異步操作更加容易。
回調地獄的舉例
假設買菜、做飯、洗碗都是異步的。
但真實的場景中,實際的操作流程是:買菜成功之後,才能開始做飯。做飯成功後,才能開始洗碗。這裏面就涉及到了多層嵌套調用,也就是回調地獄。
Promise 的基本用法
(1)使用new實例化一個Promise對象,Promise的構造函數中傳遞一個參數。這個參數是一個函數,該函數用於處理異步任務。
(2)並且傳入兩個參數:resolve和reject,分別表示異步執行成功後的回調函數和異步執行失敗後的回調函數;
(3)通過 promise.then() 處理返回結果。這裏的 p 指的是 Promise實例。
代碼舉例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// 第一步: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);
});
</script>
</body>
</html>
上方代碼中,當從接口返回的數據data.retCode
的值不同時,可能會走 resolve,也可能會走 reject,這個由你自己的業務決定。
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裏的內容
另外,resolve()和reject()這兩個方法,是可以給promise.then()傳遞參數的。