?
Promise 是什么?
Promise
是一個 JS 的異步編程解決方案,解決了傳統(tǒng)異步編程回調(diào)地獄的問題。 從語義上來說:Promise
是一個向外部傳達(dá)異步編程操作消息的對象。
Promise 的三種狀態(tài)
JS里一個promise可以有以下幾種基本狀態(tài):
- nothing happened yet
- "locked in" to another promise
- fulfilled
- rejected
其中{1,2}為pending,{3,4}為settled,{2,3,4}為resolved,{1}為unresolved。
?
Promise
對象表示一個異步操作,擁有三種狀態(tài):
-
pending
(進(jìn)行中) -
fulfilled
(已完成) -
rejected
(已失敗)
只有異步操作的結(jié)果可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)。 其中 pending
為初始狀態(tài),狀態(tài)的變化只有兩種:
-
pending
->fulfilled
(異步任務(wù)完成) -
pending
->rejected
(異步任務(wù)失?。?/li>
且一旦狀態(tài)改變,狀態(tài)就會凝固,不會再變化了。這就導(dǎo)致 Promise 一旦建立就會立即執(zhí)行,無法取消。
Promise 的基本用法
ES6 規(guī)定 Promise 是一個構(gòu)造函數(shù),用來生成 Promise
對象實例。
const promise = new Promise(function(resolve,reject){
// 異步操作
if(success){ //異步操作成功
resolve(value);
} else{ //異步操作失敗
reject(err);
}
})
復(fù)制代碼
Promise
構(gòu)造函數(shù)接收的參數(shù)是一個函數(shù),該函數(shù)有兩個由 JS 引擎指定的參數(shù):resolve
函數(shù) 和 reject
函數(shù)
-
resolve
函數(shù) 有兩個作用:- 將 Promise 狀態(tài)由
pending
->fulfilled
(等待態(tài) -> 成功態(tài)) - 將異步操作成功的結(jié)果 value 作為參數(shù)傳遞出去。(由后面講的的 then 方法接收)
- 將 Promise 狀態(tài)由
-
reject
函數(shù) 也有兩個作用:- 將 Promise 狀態(tài)由
pending
->rejected
(等待態(tài) -> 失敗態(tài)) - 將異步操作失敗的錯誤信息
err
作為參數(shù)傳遞出去。(由后面講的的then
/catch
方法接收)
- 將 Promise 狀態(tài)由
Promise 的三個實例方法 then catch finally
1. Promise.prototype.then()
Promise
實例具有 then
方法,也就是說 then
方法時定義在原型對象上的。 Promise
實例生成后,可以用 then
方法分別指定 resolve
狀態(tài)和 rejected
狀態(tài)的回調(diào)函數(shù):獲取 Promise
內(nèi)部的異步操作狀態(tài)。
promise.then(
function (value) {
console.log(value); //異步操作成功時(fulfilled 態(tài))調(diào)用
},
function (err) {
console.log(err); //異步操作失敗時(rejected 態(tài))調(diào)用
}
);
復(fù)制代碼
then
方法可以接收兩個回調(diào)函數(shù)作為參數(shù):
第一個回調(diào)函數(shù)在 promise
實例變?yōu)?fulfilled
時調(diào)用,并獲取 resolve
函數(shù)傳遞的參數(shù) value。
第二個回調(diào)函數(shù)在 promise
實例變?yōu)?rejected
時調(diào)用,并獲取 reject
函數(shù)傳遞的參數(shù) err。
then 方法的返回值是一個新的 Promise
對象,因此可以 .then
可以鏈?zhǔn)秸{(diào)用。
2. Promise.prototype.catch()
Promise
實例的 catch
方法用于指定發(fā)生錯誤時的回調(diào)函數(shù),是 .then(null, rejection)
的語法糖。
promise
.then(function (val) {
console.log(val); //異步操作成功時(fulfilled 態(tài))調(diào)用
})
.catch(function (err) {
console.log(err); //異步操作失敗時(rejected 態(tài))調(diào)用
});
復(fù)制代碼
上面代碼中, 如果 promise
對象狀態(tài)變?yōu)?fulfilled
,則會調(diào)用 then
方法指定的回調(diào)函數(shù);如果異步操作拋出錯誤,狀態(tài)就會變?yōu)?rejected
,就會調(diào)用 catch
方法指定的回調(diào)函數(shù)。另外,then
方法指定的回調(diào)函數(shù),如果運(yùn)行拋出錯誤,也會被 catch
方法捕獲。
promise
.then((val) => console.log("fulfilled:", val))
.catch((err) => console.log("rejected:", err));
// 等價于
promise
.then((val) => console.log("fulfilled:", val))
.then(null, (err) => console.log("rejected:", err));
復(fù)制代碼
如果 Promise
狀態(tài)已經(jīng)變成 resolved
,再拋出錯誤是無效的。因為 Promise
的狀態(tài)一旦改變,就永久保持該狀態(tài),不會再變了。 Promise
對象的錯誤具有冒泡性質(zhì),會一直向后傳遞,直到被捕獲為止,也就是說錯誤總會被下一個 catch
語句捕獲。
3. Promise.prototype.finally()
Promise
實例的 finally
方法用于指定不管狀態(tài)最終如何,都會執(zhí)行的函數(shù)。是 .then(function,function)
(function
相同)的語法糖。
promise.finally((message) => console.log("狀態(tài)變化了", message));
// 等價于
promise.then(
(message) => console.log("狀態(tài)變化了", message),
(message) => console.log("狀態(tài)變化了", message)
);
// 無論成功還是失敗都會執(zhí)行
復(fù)制代碼
Promise 的兩個靜態(tài)方法 all 和 race
1. Promise.all()
Promise.all(arr)
方法是掛載在 Promise
構(gòu)造函數(shù)上的靜態(tài)方法,它傳入?yún)?shù)為一個 Promise
對象數(shù)組 arr
,返回值為一個 Promise
實例:
該實例會在 Promise
對象數(shù)組 內(nèi)所有對象的狀態(tài)變?yōu)?fulfilled
時調(diào)用內(nèi)部的 resolve
函數(shù); 該實例在 Promise
對象數(shù)組 內(nèi)任意對象的狀態(tài)變?yōu)?rejected
時調(diào)用 reject
函數(shù)(reject
函數(shù)的參數(shù)為第一個錯誤的 promise
對象的 err
); 有點類似于 JS
里的與操作(&&)
:所有表達(dá)式為真時返回真,任意表達(dá)式為假時返回假。
let p1 = new Promise((resolve,reject)=>{
resolve('p1-success'),
})
let p2 = new Promise((resolve,reject)=>{
resolve('p2-success'),
})
let p3 = new Promise((resolve,reject)=>{
reject('p1-error'),
})
Promise.all([p1,p2,p3]).then(val=>{
console.log(val)
}).catch(err=>{
console.log(err)
})
//輸出 p1-error
復(fù)制代碼
需要特別注意的是,Promise.all()
獲得的成功結(jié)果的數(shù)組里面的數(shù)據(jù)順序和 Promise.all()
接收到的數(shù)組順序是一致的,即 p1
的結(jié)果在前,即便 p1
的結(jié)果獲取的比 p2
要晚。這帶來了一個絕大的好處:在前端開發(fā)請求數(shù)據(jù)的過程中,偶爾會遇到發(fā)送多個請求并根據(jù)請求順序獲取和使用數(shù)據(jù)的場景,使用 Promise.all()
毫無疑問可以解決這個問題。
2. Promise.race()
Promise.race(arr)
方法返回一個 promise
實例,一旦 arr
中的某個 promise
對象解決或拒絕,返回的 promise
就會解決或拒絕。 顧名思義,Promise.race 就是賽跑的意思,意思就是說,Promise.race([p1, p2, p3])
里面哪個結(jié)果獲得的快,就返回那個結(jié)果,不管結(jié)果本身是成功狀態(tài)還是失敗狀態(tài)。文章來源:http://www.zghlxwxcb.cn/news/detail-711190.html
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p1-success");
}, 1000);
});
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p2-success");
}, 500);
});
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("p3-error");
}, 1000);
});
Promise.race([p1, p2, p3])
.then((val) => {
console.log(val);
})
.catch((err) => {
console.log(err);
});
//輸出 p2-success
作者:Prayx
鏈接:https://juejin.cn/post/6862929170390450183
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。文章來源地址http://www.zghlxwxcb.cn/news/detail-711190.html
到了這里,關(guān)于JavaScript 異步解決方案 Promise 全解析(轉(zhuǎn)載)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!