2021-03-17 分類: 網(wǎng)站建設
Node的產(chǎn)生,大大推動了Javascript
這門語言在服務端的發(fā)展,使得前端人員可以以很低的門檻轉(zhuǎn)向后端開發(fā)。
當然,這并不代表迸發(fā)成了全棧。全棧的技能很集中,絕不僅僅是前端會寫一些HTML
和一些交互,后臺熟悉數(shù)據(jù)庫的增刪查改。
想必接觸過Node的人都知道,Node是以異步(Async)回調(diào)著稱的,其異步性提高了程序的執(zhí)行效率,但同時也減少了程序的可讀性。如果我們有幾個異步操作,并且后一個操作需要前一個操作返回的數(shù)據(jù)才能執(zhí)行,這樣按照Node的一般執(zhí)行規(guī)律,要實現(xiàn)有序的異步操作,通常是一層加一層嵌套下去。
為了解決這個問題,ES6提出了Promise
的實現(xiàn)。
Promise 對象用于一個異步操作的最終完成(或失敗)及其結(jié)果值的表示。簡單點說,它就是用于處理異步操作的,異步處理成功了就執(zhí)行成功的操作,異步處理失敗了就捕獲錯誤或者停止后續(xù)操作。
它的一般表示形式為:
new Promise(
/* executor */
function(resolve, reject) {
if (/* success */) {
// ...執(zhí)行代碼
resolve();
} else { /* fail */
// ...執(zhí)行代碼
reject();
}
}
);
其中,Promise中的參數(shù)executor
是一個執(zhí)行器函數(shù),它有兩個參數(shù)resolve
和reject
。它內(nèi)部通常有一些異步操作,如果異步操作成功,則可以調(diào)用resolve()來將該實例的狀態(tài)置為fulfilled
,即已完成的,如果一旦失敗,可以調(diào)用reject()來將該實例的狀態(tài)置為rejected
,即失敗的。
我們可以把Promise對象看成是一條工廠的流水線,對于流水線來說,從它的工作職能上看,它只有三種狀態(tài),一個是初始狀態(tài)(剛開機的時候),一個是加工產(chǎn)品成功,一個是加工產(chǎn)品失?。ǔ霈F(xiàn)了某些故障)。同樣對于Promise對象來說,它也有三種狀態(tài):
pending
fulfilled
rejected
它只有兩種狀態(tài)可以轉(zhuǎn)化,即
并且這個狀態(tài)轉(zhuǎn)化是單向的,不可逆轉(zhuǎn),已經(jīng)確定的狀態(tài)(fulfilled/rejected)無法轉(zhuǎn)回初始狀態(tài)(pending)。
Promise對象含有then方法,then()調(diào)用后返回一個Promise對象,意味著實例化后的Promise對象可以進行鏈式調(diào)用,而且這個then()方法可以接收兩個函數(shù),一個是處理成功后的函數(shù),一個是處理錯誤結(jié)果的函數(shù)。
如下:
var promise1 = new Promise(function(resolve, reject) {
// 2秒后置為接收狀態(tài)
setTimeout(function() {
resolve('success');
}, 2000);
});
promise1.then(function(data) {
console.log(data); // success
}, function(err) {
console.log(err); // 不執(zhí)行
}).then(function(data) {
// 上一步的then()方法沒有返回值
console.log('鏈式調(diào)用:' + data); // 鏈式調(diào)用:undefined
}).then(function(data) {
// ....
});
在這里我們主要關(guān)注promise1.then()方法調(diào)用后返回的Promise對象的狀態(tài),是pending
還是fulfilled
,或者是rejected
?
返回的這個Promise對象的狀態(tài)主要是根據(jù)promise1.then()方法返回的值,大致分為以下幾種情況:
轉(zhuǎn)換實例如下:
var promise2 = new Promise(function(resolve, reject) {
// 2秒后置為接收狀態(tài)
setTimeout(function() {
resolve('success');
}, 2000);
});
promise2
.then(function(data) {
// 上一個then()調(diào)用了resolve,置為fulfilled態(tài)
console.log('第一個then');
console.log(data);
return '2';
})
.then(function(data) {
// 此時這里的狀態(tài)也是fulfilled, 因為上一步返回了2
console.log('第二個then');
console.log(data); // 2
return new Promise(function(resolve, reject) {
reject('把狀態(tài)置為rejected error'); // 返回一個rejected的Promise實例
});
}, function(err) {
// error
})
.then(function(data) {
/* 這里不運行 */
console.log('第三個then');
console.log(data);
// ....
}, function(err) {
// error回調(diào)
// 此時這里的狀態(tài)也是fulfilled, 因為上一步使用了reject()來返回值
console.log('出錯:' + err); // 出錯:把狀態(tài)置為rejected error
})
.then(function(data) {
// 沒有明確指定返回值,默認返回fulfilled
console.log('這里是fulfilled態(tài)');
});
catch()方法和then()方法一樣,都會返回一個新的Promise對象,它主要用于捕獲異步操作時出現(xiàn)的異常。因此,我們通常省略then()方法的第二個參數(shù),把錯誤處理控制權(quán)轉(zhuǎn)交給其后面的catch()函數(shù),如下:
var promise3 = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('reject');
}, 2000);
});
promise3.then(function(data) {
console.log('這里是fulfilled狀態(tài)'); // 這里不會觸發(fā)
// ...
}).catch(function(err) {
// 最后的catch()方法可以捕獲在這一條Promise鏈上的異常
console.log('出錯:' + err); // 出錯:reject
});
Promise.all()接收一個參數(shù),它必須是可以迭代的,比如數(shù)組。
它通常用來處理一些并發(fā)的異步操作,即它們的結(jié)果互不干擾,但是又需要異步執(zhí)行。它最終只有兩種狀態(tài):成功或者失敗。
它的狀態(tài)受參數(shù)內(nèi)各個值的狀態(tài)影響,即里面狀態(tài)全部為fulfilled
時,它才會變成fulfilled
,否則變成rejected
。
成功調(diào)用后返回一個數(shù)組,數(shù)組的值是有序的,即按照傳入?yún)?shù)的數(shù)組的值操作后返回的結(jié)果。如下:
// 置為fulfilled狀態(tài)的情況
var arr = [1, 2, 3];
var promises = arr.map(function(e) {
return new Promise(function(resolve, reject) {
resolve(e * 5);
});
});
Promise.all(promises).then(function(data) {
// 有序輸出
console.log(data); // [5, 10, 15]
console.log(arr); // [1, 2, 3]
});
// 置為rejected狀態(tài)的情況
var arr = [1, 2, 3];
var promises2 = arr.map(function(e) {
return new Promise(function(resolve, reject) {
if (e === 3) {
reject('rejected');
}
resolve(e * 5);
});
});
Promise.all(promises2).then(function(data) {
// 這里不會執(zhí)行
console.log(data);
console.log(arr);
}).catch(function(err) {
console.log(err); // rejected
});
Promise.race()和Promise.all()類似,都接收一個可以迭代的參數(shù),但是不同之處是Promise.race()的狀態(tài)變化不是全部受參數(shù)內(nèi)的狀態(tài)影響,一旦參數(shù)內(nèi)有一個值的狀態(tài)發(fā)生的改變,那么該Promise的狀態(tài)就是改變的狀態(tài)。就跟race
單詞的字面意思一樣,誰跑的快誰贏。如下:
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 300, 'p1 doned');
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 50, 'p2 doned');
});
var p3 = new Promise(function(resolve, reject) {
setTimeout(reject, 100, 'p3 rejected');
});
Promise.race([p1, p2, p3]).then(function(data) {
// 顯然p2更快,所以狀態(tài)變成了fulfilled
// 如果p3更快,那么狀態(tài)就會變成rejected
console.log(data); // p2 doned
}).catch(function(err) {
console.log(err); // 不執(zhí)行
});
Promise.resolve()接受一個參數(shù)值,可以是普通的值
,具有then()方法的對象
和Promise實例
。正常情況下,它返回一個Promise對象,狀態(tài)為fulfilled
。但是,當解析時發(fā)生錯誤時,返回的Promise對象將會置為rejected
態(tài)。如下:
// 參數(shù)為普通值
var p4 = Promise.resolve(5);
p4.then(function(data) {
console.log(data); // 5
});
// 參數(shù)為含有then()方法的對象
var obj = {
then: function() {
console.log('obj 里面的then()方法');
}
};
var p5 = Promise.resolve(obj);
p5.then(function(data) {
// 這里的值時obj方法里面返回的值
console.log(data); // obj 里面的then()方法
});
// 參數(shù)為Promise實例
var p6 = Promise.resolve(7);
var p7 = Promise.resolve(p6);
p7.then(function(data) {
// 這里的值時Promise實例返回的值
console.log(data); // 7
});
// 參數(shù)為Promise實例,但參數(shù)是rejected態(tài)
var p8 = Promise.reject(8);
var p9 = Promise.resolve(p8);
p9.then(function(data) {
// 這里的值時Promise實例返回的值
console.log('fulfilled:'+ data); // 不執(zhí)行
}).catch(function(err) {
console.log('rejected:' + err); // rejected: 8
});
Promise.reject()和Promise.resolve()正好相反,它接收一個參數(shù)值reason
,即發(fā)生異常的原因。此時返回的Promise對象將會置為rejected
態(tài)。如下:
var p10 = Promise.reject('手動拒絕');
p10.then(function(data) {
console.log(data); // 這里不會執(zhí)行,因為是rejected態(tài)
}).catch(function(err) {
console.log(err); // 手動拒絕
}).then(function(data) {
// 不受上一級影響
console.log('狀態(tài):fulfilled'); // 狀態(tài):fulfilled
});
總之,除非Promise.then()方法內(nèi)部拋出異?;蛘呤敲鞔_置為rejected態(tài),否則它返回的Promise的狀態(tài)都是fulfilled態(tài),即完成態(tài),并且它的狀態(tài)不受它的上一級的狀態(tài)的影響。
大概常用的方法就寫那么多,剩下的看自己實際需要再去了解。
解決Node回調(diào)地獄的不止有
Promise
,還有
分享名稱:總結(jié)一些Promise常用的用法
文章路徑:http://www.rwnh.cn/news/105329.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、建站公司、電子商務、自適應網(wǎng)站、品牌網(wǎng)站建設、網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源:
創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容