前端學(xué)習(xí)9 Promise
promise,是異步操作(讀取文件,發(fā)起網(wǎng)絡(luò)請(qǐng)求)的一種解決方案,解決了回調(diào)地獄(傳統(tǒng)的解決方案)的出現(xiàn)。
1.回調(diào)地獄
在異步編程的領(lǐng)域中,回調(diào)地獄是一個(gè)經(jīng)常困擾開發(fā)者的難題。它的產(chǎn)生源于回調(diào)函數(shù)的過度嵌套,從而導(dǎo)致代碼結(jié)構(gòu)變得錯(cuò)綜復(fù)雜。當(dāng)一個(gè)回調(diào)函數(shù)內(nèi)部嵌套另一個(gè)回調(diào)函數(shù)時(shí),就像是在一個(gè)盒子里不斷嵌套更小的盒子,層層深入。
例如,假設(shè)我們要模擬發(fā)送三個(gè)異步請(qǐng)求,并且第二個(gè)請(qǐng)求依賴于第一個(gè)請(qǐng)求結(jié)果中的某個(gè)特定值作為參數(shù),第三個(gè)請(qǐng)求又依賴于第二個(gè)請(qǐng)求結(jié)果中的某個(gè)值作為參數(shù)。如果使用傳統(tǒng)的回調(diào)函數(shù)方式,代碼可能會(huì)呈現(xiàn)出如下的形態(tài):
function fn() {
setTimeout(function () {
console.log("111");
setTimeout(function () {
console.log("222");
setTimeout(function () {
console.log("333");
}, 1000);
}, 2000);
}, 3000);
}
fn();
在這段代碼中,setTimeout函數(shù)模擬了異步操作,鎖著嵌套函數(shù)的一層層增加,代碼就像一團(tuán)亂麻,所以我們使用Promise來解決回調(diào)地獄這個(gè)問題,之后我們會(huì)學(xué)習(xí)最先進(jìn)的異步方案:async 和 await。
2. promise 對(duì)象
Promise對(duì)象是一個(gè)獨(dú)立的個(gè)體,通過自身的狀態(tài)來控制異步操作。promise一共有三種狀態(tài),每一種狀態(tài)都代表著異步操作的一個(gè)特定階段:
1.pedding :進(jìn)行中,Promise處于等待;
2.fulfilled :異步操作已經(jīng)成功;
3.rejected :異步操作已經(jīng)失敗;
3. Promise 實(shí)例
const ps = new Promise(function (resolve,reject) {});
這樣就創(chuàng)建了一個(gè)Promise實(shí)例,Promise接受一個(gè)函數(shù)類型作為參數(shù),這個(gè)函數(shù)有接受兩個(gè)參數(shù)resolve,reject。分別表示成功回調(diào)(fulfilled)和失敗回調(diào)(rejected)。
4.Promise 方法
為了更好的控制下一步執(zhí)行,我們有三個(gè)實(shí)例方法:then,catch,finally;
4.1 then 方法
then方法一般接受兩個(gè)參數(shù)resolve,reject。
const ps2 = new Promise(function (resolve, reject) {
let number = 9;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps2.then(
function (res) {
console.log(res);
},
function (err) {
console.log(err);
}
);
4.2 catch 方法
then方法支持鏈?zhǔn)秸{(diào)用,但是then的執(zhí)行嚴(yán)重依賴上一步的結(jié)果,上一步?jīng)]有結(jié)果,那么下一步就不會(huì)執(zhí)行,但是每一步都寫reject特別麻煩,所以誕生了catch,then就可以省略reject方法,reject交給catch執(zhí)行,同時(shí)catch還可以捕獲resolve的異常。
const ps2 = new Promise(function (resolve, reject) {
let number = 9;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps2
.then(function (res) {})
.catch(function (err) {
console.log(err);
});
4.3 finally 方法
無論成功還是失敗都需要執(zhí)行一些操作,就誕生了 finally。我們可以在這做一些清理工作。
const ps2 = new Promise(function (resolve, reject) {
let number = 9;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps2
.then(function (res) {})
.catch(function (err) {
console.log(err);
})
.finally(function () {
console.log("end");
});
5.then的鏈?zhǔn)秸{(diào)用
then方法返回的是一個(gè)新的Promise實(shí)例,也就是promise能鏈?zhǔn)綍鴮懙脑颉?/p>
const ps = new Promise(function (resolve, reject) {
let number = 10;
if (number >= 10) {
resolve(number);
} else {
reject("number 小于10");
}
});
ps.then(function (res) {
return res * 10;
})
.then(function (res) {
return res + 2;
})
.then(function (res) {
if (res > 100) {
console.log(res);
} else {
console.log("最后結(jié)果小于100");
}
});
其中return res * 10;創(chuàng)建一個(gè)新的Promise,其狀態(tài)為fulfilled,并攜帶結(jié)果值 100。 我們來可以返回一個(gè)自己創(chuàng)建的Promise對(duì)象。
function date() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('相親了');
// 可以傳遞一個(gè)對(duì)象表示相親的結(jié)果
resolve('和最愛的人相親了');
}, 2000);
});
}
function marry() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('結(jié)婚了');
// 傳遞結(jié)婚的相關(guān)信息
resolve('和最愛的人結(jié)婚了');
}, 1000);
});
}
function baby() {
console.log('出生了');
}
date()
.then(resultFromDate => {
console.log('相親結(jié)果:', resultFromDate);
return marry();
})
.then(resultFromMarry => {
console.log('結(jié)婚信息:', resultFromMarry);
baby();
});
5.Promise 原型方法
為了滿足更多的業(yè)務(wù)需要,又誕生了 6 個(gè)原型方法 Promise.all()、Promise.allSettled()、Promise.any()、Promise.race()、Promise.reject()、Promise.resolve()。且都會(huì)返回一個(gè)確定狀態(tài)的 Promsie 對(duì)象。
5.1 Promise.all()
通過數(shù)組的形式傳入異步操作,所有的異步執(zhí)行都成功,才執(zhí)行成功,如果有一個(gè)失敗了,就執(zhí)行失敗。
Promise.all([ps1, ps2])
.then(function (res) {
console.log("都成功", res);
})
.catch(function (err) {
console.log(err);
});
5.2 Promise.allSettled()
所有執(zhí)行都有結(jié)果了就執(zhí)行,無論成功還是失敗。
Promise.allSettled([ps1, ps2, ps3, ps4]).then(function (res) {
console.log("都返回結(jié)果", res);
});
5.3 Promise.any()
任意異步成功了就執(zhí)行。
Promise.any([ps1, ps2, ps3, ps4]).then(function (res) {
console.log("任意成功", res);
});
5.4 Promise.race()
任意異步成功或失敗就執(zhí)行。
5.5 Promise.reject()
返回一個(gè)狀態(tài)為 rejected 的 Promise 對(duì)象。
5.6 Promise.resolve()
會(huì)接收 4 種類型的參數(shù):promise 實(shí)例 、具有 then 方法的對(duì)象、沒有 then 方法的對(duì)象、不傳參
當(dāng)參數(shù)是一個(gè) Promise 實(shí)例時(shí),直接返回這個(gè)實(shí)例。
Promise.resolve(ps1);
當(dāng)參數(shù)是一個(gè)具有 then 方法的對(duì)象時(shí),將這個(gè)對(duì)象轉(zhuǎn)為 Promise 對(duì)象,并立即執(zhí)行對(duì)象的 then 方法
let obj = {
name: "yqcoder",
then(resolve) {
resolve(this.name);
},
};
Promise.resolve(obj);
當(dāng)參數(shù)是一個(gè)沒有 then 方法的對(duì)象,或者參數(shù)不是對(duì)象時(shí),就會(huì)返回狀態(tài)為 fulfilled 的新的 Promise 對(duì)象,并將參數(shù)傳入下一個(gè) then。
let obj = {
name: "yqcoder",
};
let ps = Promise.resolve(obj);
ps.then(function (res) {
console.log("結(jié)果", res);
});
當(dāng)不帶任何參數(shù)時(shí),就會(huì)返回一個(gè)狀態(tài)為 fulfilled 的 Promise 對(duì)象
Promise.resolve();
#前端學(xué)習(xí)#