一文帶你了解promise并解決回調(diào)地獄
Promise
為什么需要promise
需求
通過ajax請求id,再根據(jù)id請求用戶名,再根據(jù)用戶名獲取email
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./jquery-3.6.0.js"></script>
</head>
<body>
<script>
//通過ajax請求拿到用戶id
$.ajax({
type:"GET",
url:"./data1.json",
success:function(res){
let {id} = res;
console.log(id);
//通過用戶id找到用戶名
$.ajax({
type:"get",
url:'./data2.json',
data:{id},
success:function(res){
let {username} = res;
console.log(username);
//通過用戶名找到用戶郵箱
$.ajax({
type:"GET",
url:"./data3.json",
data:{username},
success:function(res){
let {email} = res;
console.log(email);
}
})
}
})
}
})
</script>
</body>
</html>
回調(diào)地獄
在回調(diào)函數(shù)中嵌套回調(diào)
在上述代碼中通過不斷請求數(shù)據(jù),代碼逐級向外遞歸,形成了回調(diào)地獄。
使用promise就可以完美解決,并且讓我們的代碼更加美觀。
Promise的基本使用
Promise是一個構(gòu)造函數(shù),通過new關(guān)鍵字實例化對象.
語法:
new promise((reso1ve,reject)=>{})
Promise接受一個函數(shù)作為參數(shù)
在參數(shù)函數(shù)中接受兩個參數(shù)
- resolve:
- reject:
promise實例
promise實例有兩個屬性:
- state:狀態(tài)
- result:結(jié)果

promise的狀態(tài)
- pending(準備,待解決,進行中)
- fulfilled(已完成,成功)
- rejected(已拒絕,失敗)
promise狀態(tài)的改變
通過調(diào)用resolve和reject改變當(dāng)前promise對象的狀態(tài)。
- 改為fulfilled
let p = new Promise((resolve,reject)=>{
resolve(); //調(diào)用resolve將狀態(tài)改為fulfilled
});
console.log(p)

- 改為rejected
let p = new Promise((resolve,reject)=>{
reject();//調(diào)用reject將狀態(tài)改為rejected
});
console.log(p)

注意:promise狀態(tài)的改變是一次性的,即不能同時調(diào)用resolve和reject,若同時調(diào)用則狀態(tài)只改變一次。
promise的結(jié)果
promise的結(jié)果是通過傳遞resolve/reject的參數(shù)來獲得的
let p = new Promise((resolve,reject)=>{
resolve("成功")
})
console.log(p);

同理,reject也是如此:
promise方法
then方法
then方法中有兩個參數(shù),且都為函數(shù)作為參數(shù)。
如:
let p = new Promise((resolve,reject)=>{
resolve("成功")
})
p.then(()=>{
console.log('成功時執(zhí)行');
},()=>{
console.log("失敗時執(zhí)行");
})
console.log(p);
- 第一個函數(shù)參數(shù)
當(dāng)promise的狀態(tài)為fulfilled時,執(zhí)行該函數(shù) - 第二個函數(shù)參數(shù)
當(dāng)promise的狀態(tài)為rejected時,執(zhí)行該函數(shù)

通過then方法獲取promise的結(jié)果
通過then方法中的函數(shù)傳遞形參即可獲得promise的結(jié)果;
let p = new Promise((resolve,reject)=>{
resolve("成功")
})
p.then((value)=>{
console.log('成功時執(zhí)行',value);
},(reason)=>{
console.log("失敗時執(zhí)行",reason);
})
console.log(p);

總結(jié):promise的狀態(tài)用來判斷then方法執(zhí)行成功或是失敗的函數(shù),promise的結(jié)果則是作為實參傳遞給then方法的函數(shù)參數(shù)的形參。
then方法的返回值
then方法返回的為一個新的promise對象。且該promise對象的狀態(tài)為pending,then方法為一個同步操作,then中的函數(shù)參數(shù)為異步操作。

如上圖我們就可以看到then方法的返回值仍然為一個promise對象,且在剛生成該對象時的狀態(tài)為pending。
由此衍生出了鏈式操作:
new Promise(()=>{}).then().then()
在該操作中,如果promise對象的狀態(tài)不改變則不會執(zhí)行then方法中的函數(shù)。那么在then方法返回的promise對象中如何讓其狀態(tài)改變呢??
- 使用return可以將then方法返回的promise對象狀態(tài)改為fulfilled。
- 在then方法中書寫錯誤代碼,即可將其promise對象狀態(tài)改為rejected
實例:
let p = new Promise((res,rej)=>{
res('蘇涼');
})
let t = p.then((value)=>{
return "name:"+value;
},(reason)=>{
console.log("執(zhí)行失?。?);
})
t.then((value)=>{
console.log(value);
},(reason)=>{
console.log(reason);
})
console.log(t);

catch方法
catch方法在promise對象的狀態(tài)為rejected時亦或者是輸入錯誤代碼時被調(diào)用,并返回錯誤原因。
let p = new Promise((res,rej)=>{
throw newError("出錯啦!")
})
p.catch((reason)=>{
console.log(reason);
})
console.log(p);

解決回調(diào)地獄
//封裝Ajax請求函數(shù)
function getAjax(path,data){
return new Promise((resolve,reject)=>{
$.ajax({
type:'get',
url:path,
data:{data},
success:function(res){
resolve(res)
},
error:function(res){
reject(res)
}
})
})
}
getAjax('./data1.json')
.then((value)=>{
let id = {value};
return getAjax("./data2.json",id)
})
.then((value)=>{
let {username} = value;
return getAjax('./data3.json',username)
})
.then((value)=>{
console.log(value);
})

以上就是一文帶你了解promise并解決回調(diào)地獄的詳細內(nèi)容,更多關(guān)于promise回調(diào)地獄的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
用Javascript評估用戶輸入密碼的強度(Knockout版)
早上看到博友6點多發(fā)的一篇關(guān)于密碼強度的文章(連接),甚是感動(周末大早上還來發(fā)文)2011-11-11
原生js添加節(jié)點appendChild、insertBefore方式
這篇文章主要介紹了原生js添加節(jié)點appendChild、insertBefore方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
詳解如何解決使用JSON.stringify時遇到的循環(huán)引用問題
這篇文章主要介紹了詳解如何解決使用JSON.stringify時遇到的循環(huán)引用問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
BOOTSTRAP時間控件顯示在模態(tài)框下面的bug修復(fù)
這篇文章主要介紹了BOOTSTRAP時間控件顯示在模態(tài)框下面的bug修復(fù),需要的朋友可以參考下2015-02-02
JS/HTML5游戲常用算法之路徑搜索算法 A*尋路算法完整實例
這篇文章主要介紹了JS/HTML5游戲常用算法之路徑搜索算法 A*尋路算法,結(jié)合完整實例形式分析了A*尋路算法的具體實現(xiàn)技巧,代碼備有詳盡的注釋便于理解,需要的朋友可以參考下2018-12-12
Web技術(shù)實現(xiàn)移動監(jiān)測的介紹
移動偵測,一般也叫運動檢測,常用于無人值守監(jiān)控錄像和自動報警。通過攝像頭按照不同幀率采集得到的圖像會被 CPU 按照一定算法進行計算和比較,當(dāng)畫面有變化時,如有人走過,鏡頭被移動,計算比較結(jié)果得出的數(shù)字會超過閾值并指示系統(tǒng)能自動作出相應(yīng)的處理2017-09-09

