Promise到底是個啥玩意

Promise到底是個啥玩意
1. 回調地域在學習 Promise 之前 , 我們先看一下什么是回調地獄:
這里我們模擬三個請求接口:

  1. 獲取產品類別
// 1. 獲取類別信息const getCategory = () => {// 模擬請求let res = {code: 200message: \"請求成功\"data: [{ id: 1 name: \"水果\"{ id: 2 name: \"圖書\"
;return res;;
  1. 根據類別 id 獲取產品信息
// 2. 根據類別 id 獲取產品信息const getProductByCategoryId = (categoryId) => {// 模擬請求let res = {code: 200message: \"請求成功\"data: [{ id: 111 categoryId: 1 name: \"蘋果\"{ id: 112 categoryId: 1 name: \"香蕉\"{ id: 113 categoryId: 1 name: \"百香果\"
;return res;;
  1. 根據產品 id 獲取產品價格
// 3. 根據產品id獲取產品價格const getPriceByProductId = (productId) => {// 模擬請求let res = {code: 200message: \"請求成功\"data: { id: 1001 productId: 111 price: 112.23 unitPrice: 1235.23;return res;;接下來我們去獲取第一個類別下第一個產品的單位價格信息:
let unitPrice = 0.0;// 獲取產品價格const getProductPrice = () => {let categoryRes = getCategory();if (categoryRes.code === 200) {let produceRes = getProductByCategoryId(1);if (produceRes.code === 200) {let priceRes = getPriceByProductId(1);if (priceRes.code === 200) {unitPrice = res.data.unitPrice;;我們發現在 getProductPrice 這個方法中 , 第一個請求接口的結果要作為第二個請求接口的參數 , 以此類推就會出現層層嵌套 , 回調里面套回調 , 這就是所謂的“回調地獄” 。
如果請求的接口太多 , 那代碼寫起來可就太苦逼了 , 就跟套娃一樣 。

所以為了解決回調地獄的問題 , 提高代碼的可讀性 , Promise 應運而生 。
2. 邂逅 PromisePromise 是異步編程的一種解決方案 。 它本質上是一個構造函數 , 可以構建一個 Promise 對象 。
Promise 構造函數接受一個函數作為參數 , 該函數的兩個參數分別是 resolve 和 reject。 對象上有 then、catch、finall 方法 。
Promise 有三種狀態:pending、fulfilled、rejected:
  • pending:它的意思是待定的 , 相當于是一個初始狀態 。 創建 Promise 對象時就是一個初始狀態 。
  • fulfilled:成功 。 當調用 resolved 方法后 , Promise 對象的狀態就會從 pending 切換到 fulfilled , 且不可改變 。
  • rejected:失敗 。 當調用 reject 方法后 , Promise 對象的狀態就會從 pending 切換到 reject , 且不可改變 。
看了上面的解釋 , 你可能還是有點懵逼 , 接下來我用通俗易懂的語言解釋一下 Promise 是個什么玩意:
1.Promise 就是一個用來封裝 HTTP 請求的工具 。
2.我們請求后臺接口獲取數據 , 如果請求成功 , 就調用 Promise 的 resolve 方法 , 并將返回的數據作為該方法的參數 。 如果請求失敗 , 就調用 Promise 的 reject 方法 , 并將返回的錯誤信息作為該方法的參數 。
3.然后我們將一個 Promise 對象作為該請求接口的返回值返回 。
4.因為該接口返回一個 Promise 對象 , 所以我們調用該接口的時候就可以直接用.then()處理成功的信息 , 用 .catch() 處理失敗的信息了 。
接下來我們將上面的例子用 Promise 改造一下 , 有了真實案例 , 大家對 Promise 的理解就更清晰明了了 。
3. 使用 Promise
  1. 獲取類別信息
const getCategory = () => {// 返回結果封裝成 Promise 對象return new Promise((resolve reject) => {// 模擬請求let res = {code: 200message: \"請求成功\"data: [{ id: 1 name: \"水果\"
;if (res.code == 200) {resolve(res);else {reject(res););;
  1. 根據類別 id 獲取產品信息
const getProductByCategoryId = (categoryId) => {return new Promise((resolve reject) => {// 模擬請求let res = {code: 200message: \"請求成功\"data: [{ id: 111 categoryId: 1 name: \"蘋果\"{ id: 112 categoryId: 1 name: \"香蕉\"{ id: 113 categoryId: 1 name: \"百香果\"
;if (res.code == 200) {resolve(res);else {reject(res););;
  1. 根據產品 id 獲取產品價格
const getPriceByProductId = (productId) => {return new Promise((resolve reject) => {// 模擬請求let res = {code: 200message: \"請求成功\"data: { id: 1001 productId: 111 price: 112.23 unitPrice: 1235.23;if (res.code == 200) {resolve(res);else {reject(res););;4.獲取第一個類別下第一個產品的單位價格信息
Promise 最常用的就是鏈式調用格式:
let unitPrice = 0.0;// 獲取產品價格const getProductPrice = () => {getCategory().then(res => {// 類別 idlet id = res.data[0
.id;// 返回一個 Promise 對象return getProductByCategoryId(id);).then(res => {// 產品 idlet id = res.data[0
.id;return getPriceByProductId(id);).then(res => {unitPrice = res.data.unitPrice;);
當然我們在日常使用過程中一般都是這種格式:
getMethod().then(res => {// 請求成功).catch(error=>{// 異常).finally(()=>{// 不管成功還是異常都要執行)4. async 和 await雖然有了 Promise 之后 , 代碼的可讀性有了很大提高 。 但是 ES7 又引入了 async 和 await 來簡化 Promise 調用操作 , 實現了以異步操作像同步的方式去執行 。
說白了async 和 await 就是對 Promise 進行了封裝 。
語法:
await 和 async 是成對出現的 , 如果寫了 await 必須要寫 async , 否則會報錯 。 如果只寫 async , 那返回的就是一個 Promise 對象
舉例:
let unitPrice = 0.0;// 獲取產品價格const getProductPrice = async () => {let res1 = await getCategory();let categoryId = res1.data[0
.id;let re2 = await getProductByCategoryId(categoryId);let productId = re2.data[0
.id;let re3 = await getPriceByProductId(productId);unitPrice = res3.data.unitPrice;;
如果只寫 async返回的就是一個 Promise 對象
const getProductPrice = async () => {getCategory().then(res=>{let categoryId =res.data[0
.id);const getCategory = async () => {// 模擬請求let res = {code: 200message: \"請求成功\"data: [{ id: 1 name: \"水果\"{ id: 2 name: \"圖書\"
;return res;;
那為什么說 async 和 await 實現了異步編程同步化呢?
因為 await 這個命令的意思就是等這一行的異步方法執行成功后 , 然后才能執行下一行代碼 , 否則就一直等待 , 下面的代碼就執行不了 。
所以雖然請求后臺的接口是異步的 , 但是 await 在語法層面實現了同步 。
5. 答疑5.1 同步請求和異步請求同步請求:當發送一個同步請求時 , 會暫停后面的代碼執行 , 等待請求的返回結果 , 然后再繼續執行下一行代碼 。
異步請求:當發送一個異步請求時 , 會繼續執行后面的代碼而不會等待請求的返回結果 。 當請求完成后 , 再通過回調函數或事件處理函數來處理返回的數據 。
1.同步請求就會依次打?。 ?、2 。 如果第一個方法執行時間比較長 , 那就一直等待 。
const getProductPrice =() => {console.log(\"1\");console.log(\"2\")2.異步請求可能會先打印 2 , 后打印 1 。
const getProductPrice = async() => {console.log(\"1\");console.log(\"2\")5.2 promise 和 axios 什么關系Promise 是 JavaScript 中用于異步編程的一個對象 , 而 axios 是 用來發送 HTTP 請求的工具庫 。
Promise 對 axios 的返回結果進行了封裝 。 所以當你發送一個 axios 請求 , 會返回一個 Promise 對象 。 然后你就可以調用 .then、.catch方法了 。
5.3 promise 和 async/await 什么關系1.async/await 對 promise 進行了封裝 。
2.async/await 是用同步語法去獲取異步請求 , 徹底消滅回調函數 。
3.只有 async , 返回的是 Promise 對象 。
【Promise到底是個啥玩意】4.await 相當于 Promise 的 then

    推薦閱讀