js基礎(chǔ)之Promise詳解
1. 是什么
Promise是一種異步編程的解決方案,用于處理異步操作并返回結(jié)果。
主要作用是解決回調(diào)函數(shù)嵌套(回調(diào)地獄)的問(wèn)題,使異步操作更加清晰、易于理解和維護(hù)。
2. 怎么用
Promise有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失?。.?dāng)一個(gè)Promise被創(chuàng)建時(shí),它的狀態(tài)為pending。當(dāng)異步操作完成并成功時(shí),Promise的狀態(tài)會(huì)變?yōu)閒ulfilled,并返回一個(gè)結(jié)果。當(dāng)異步操作失敗時(shí),Promise的狀態(tài)會(huì)變?yōu)閞ejected,并返回一個(gè)錯(cuò)誤信息。
基本語(yǔ)法
// 創(chuàng)建一個(gè)promise
let promise = new Promise(function(resolve, reject) {// 異步操作if (異步操作成功) {resolve(value); // 將異步操作的結(jié)果傳遞給Promise對(duì)象,狀態(tài)變?yōu)閒ulfilled} else {reject(error); // 將異步操作的錯(cuò)誤信息傳遞給Promise對(duì)象,狀態(tài)變?yōu)閞ejected}
});promise.then(function(result) {// 異步操作成功時(shí)的處理代碼
}).catch(function(error) {// 異步操作失敗時(shí)的處理代碼
});
常用方法
1.then
then中一般傳入兩個(gè)參數(shù)(函數(shù)),第一個(gè)對(duì)應(yīng)resolve成功的回調(diào),第二個(gè)對(duì)應(yīng)reject失敗的回調(diào),如下
function onResolved(res) {
?console.log("resolved-" + res); // resolved-成功了
}
function onRejected(err) {
?console.log("rejected-" + err); // rejected-失敗了
}
new Promise((resolve, reject) => {
?resolve('成功了');// reject('失敗了')
}).then(onResolved, onRejected);
then的第二個(gè)參數(shù)就等同于catch方法,但是需要注意
Promise內(nèi)部報(bào)錯(cuò),reject拋出錯(cuò)誤后,then的第二個(gè)參數(shù)和catch方法都存在的情況下,只有then的第二個(gè)參數(shù)能捕獲到,如果then的第二個(gè)參數(shù)不存在,catch方法會(huì)捕捉到
catch不僅捕捉promise中拋出的錯(cuò)誤,還會(huì)捕捉前面then中的錯(cuò)誤
2.catch
捕捉promise錯(cuò)誤函數(shù),和then的第二個(gè)參數(shù)(函數(shù))作用一樣,處理錯(cuò)誤,由于Promise拋出錯(cuò)誤具有冒泡性質(zhì),能夠不斷傳遞,會(huì)傳到catch中,所以一般來(lái)說(shuō)所有錯(cuò)誤處理放在catch中,then中只處理成功的,同時(shí)catch還會(huì)捕捉then中第一個(gè)參數(shù)(函數(shù))拋出的異常
new Promise((resolve, reject) => {
?reject();
}).catch((err)=> {
?console.log(err)
});
3.finally
finally 方法沒(méi)有參數(shù),也不會(huì)改變 Promise 的狀態(tài),它只是在 Promise 結(jié)束時(shí)提供了一個(gè)通知機(jī)制,讓我們可以在 Promise 結(jié)束后執(zhí)行一些清理工作(比如操作文件的時(shí)候關(guān)閉文件流)。
Promise對(duì)象的finally()方法用于在Promise成功或拒絕時(shí)使用
不管promise最后的狀態(tài),在執(zhí)行完then或catch指定的回調(diào)函數(shù)以后,都會(huì)執(zhí)行finally方法指定的回調(diào)函數(shù),它可以防止Promise的then()和catch()方法中的代碼重復(fù)。
// 栗子1
function onFinally() {
?console.log('結(jié)束');
}
new Promise((resolve, reject) => {}).finally(onFinally);
// 栗子2
let promise = new Promise((resolve,reject) => {
? ?resolve('resolve')
})
promise.then((res) => {
? ?console.log(res)
}).catch((err) => {
? ?console.log(err)
}).finally(()=> {
? ?console.log('this finally')
})
// resolve
// this finally
4.all
接受一個(gè)具有Iterable接口的類型,如數(shù)組,Map,Set,傳入多個(gè)promise,
每一個(gè)promise執(zhí)行成功resolve,最后才執(zhí)行成功(返回一個(gè)Promise實(shí)例),進(jìn)入then,否則失敗進(jìn)入catch
function p1() {
?var promise1 = new Promise(function (resolve, reject) {
? ? ?console.log("p1的第一條輸出語(yǔ)句");
? ? ?resolve("p1完成");
?});
?return promise1;
}
function p2() {
?var promise2 = new Promise(function (resolve, reject) {
? ? ?console.log("p2的第一條輸出語(yǔ)句");
? ? ?setTimeout(() => {
? ? ? ?console.log("p2的第二條輸出語(yǔ)句");
? ? ? ?resolve("p2完成");}, 2000);
? ? ?});return promise2;
}
function p3() {
?var promise3 = new Promise(function (resolve, reject) {
? ? ?console.log("p3的第一條輸出語(yǔ)句");
? ? ?resolve("p3完成");
?});
?return promise3;
}
Promise.all([p1(), p2(), p3()]).then(function (data) {
?console.log(data);
});// 輸出
// p1的第一條輸出語(yǔ)句;
// p2的第一條輸出語(yǔ)句;
// p3的第一條輸出語(yǔ)句;
// p2的第二條輸出語(yǔ)句[("p1完成", "p2完成", "p3完成")];
var p1 = new Promise((resolve, reject) => {
?setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
?setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
?setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
?setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
?reject('reject');// setTimeout(resolve, 5000, 'five');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
?console.log(values); // [ 'one', 'two', 'three', 'four', 'five' ]
}, reason => {
?console.log(reason) // reject
});
5.allSettled
接受一個(gè)具有Iterable接口的類型,如數(shù)組,Map,Set,傳入多個(gè)promise,
每個(gè)promise狀態(tài)改變成fulfilled或者rejected之后返回,返回的是一個(gè)數(shù)組對(duì)象,對(duì)象中有狀態(tài)status和每一項(xiàng)的返回結(jié)果value
Promise.allSettled([p1, p2, p3, p4, p5]).then(values => {console.log(values);
}, reason => {console.log(reason)
});
// [
// ? { status: 'fulfilled', value: 'one' },
// ? { status: 'fulfilled', value: 'two' },
// ? { status: 'fulfilled', value: 'three' },
// ? { status: 'fulfilled', value: 'four' },
// ? { status: 'rejected', reason: 'reject' }
// ]
6.race
以快為準(zhǔn),數(shù)組中所有的promise對(duì)象,有一個(gè)先執(zhí)行了何種狀態(tài),該對(duì)象就為何種狀態(tài),并執(zhí)行相應(yīng)函數(shù)
接受一個(gè)具有Iterable接口的類型,如數(shù)組,Map,Set,傳入多個(gè)promise,
其中有一個(gè)promise返回了,不管是fulfilled或者rejected,直接返回這個(gè)promise的結(jié)果
function p1() {
?var promise1 = new Promise(function (resolve, reject) {
? ? ?console.log("p1的第一條輸出語(yǔ)句");
? ? ?resolve("p1完成");
?});
?return promise1;
}
function p2() {
?var promise2 = new Promise(function (resolve, reject) {
? ? ?console.log("p2的第一條輸出語(yǔ)句");
? ? ?setTimeout(() => {
? ? ? ?console.log("p2的第二條輸出語(yǔ)句");
? ? ? ?resolve("p2完成");
? ? ?}, 2000);
?});
?return promise2;
}
function p3() {
?var promise3 = new Promise(function (resolve, reject) {
? ?console.log("p3的第一條輸出語(yǔ)句");
? ?resolve("p3完成");
?});
?return promise3;
}
Promise.race([p1(), p2(), p3()]).then(function (data) {
?console.log(data);
});// 輸出
// p1的第一條輸出語(yǔ)句
// p2的第一條輸出語(yǔ)句
// p3的第一條輸出語(yǔ)句
// p1完成
7.any
接受一個(gè)具有Iterable接口的類型,如數(shù)組,Map,Set,傳入多個(gè)promise,
當(dāng)傳入的任何一個(gè)promise成功的時(shí)候,不管其他是否成功或者失敗,會(huì)把成功的那個(gè)promise返回
如果傳入的是一個(gè)空的數(shù)組(Map,Set),返回一個(gè)已失敗狀態(tài)的promise,如下

注意
Promise的以上方法都屬于 微任務(wù)。當(dāng)Promise狀態(tài)變?yōu)橐呀鉀Q(resolved)或被拒絕(rejected)時(shí),這些方法會(huì)產(chǎn)生微任務(wù)。這些微任務(wù)會(huì)在主線程空閑時(shí)按照順序依次執(zhí)行。
3. 有什么問(wèn)題
首先,無(wú)法取消 Promise,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消。
其次,如果不設(shè)置回調(diào)函數(shù),Promise 內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。
第三,當(dāng)處于 Pending 狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)。
原文鏈接:https://www.dianjilingqu.com/746796.html