摘要:含義對象用于一個異步操作的最終完成或失敗及其結(jié)果值的表示。同樣對于對象來說,它也有三種狀態(tài)初始狀態(tài)也稱為未定狀態(tài),就是初始化時,調(diào)用執(zhí)行器函數(shù)后的狀態(tài)。此時返回的對象將會置為態(tài)。
Node的產(chǎn)生,大大推動了Javascript這門語言在服務(wù)端的發(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 對象用于一個異步操作的最終完成(或失?。┘捌浣Y(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
初始狀態(tài),也稱為未定狀態(tài),就是初始化Promise時,調(diào)用executor執(zhí)行器函數(shù)后的狀態(tài)。
fulfilled
完成狀態(tài),意味著異步操作成功。
rejected
失敗狀態(tài),意味著異步操作失敗。
它只有兩種狀態(tài)可以轉(zhuǎn)化,即
操作成功
pending -> fulfilled
操作失敗
pending -> rejected
并且這個狀態(tài)轉(zhuǎn)化是單向的,不可逆轉(zhuǎn),已經(jīng)確定的狀態(tài)(fulfilled/rejected)無法轉(zhuǎn)回初始狀態(tài)(pending)。
方法 Promise.prototype.then()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()方法返回的值,大致分為以下幾種情況:
如果then()方法中返回了一個參數(shù)值,那么返回的Promise將會變成接收狀態(tài)。
如果then()方法中拋出了一個異常,那么返回的Promise將會變成拒絕狀態(tài)。
如果then()方法調(diào)用resolve()方法,那么返回的Promise將會變成接收狀態(tài)。
如果then()方法調(diào)用reject()方法,那么返回的Promise將會變成拒絕狀態(tài)。
如果then()方法返回了一個未知狀態(tài)(pending)的Promise新實例,那么返回的新Promise就是未知狀態(tài)。
如果then()方法沒有明確指定的resolve(data)/reject(data)/return data時,那么返回的新Promise就是接收狀態(tài),可以一層一層地往下傳遞。
轉(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)"); });Promise.prototype.catch()
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()
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.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()
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.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)的影響。
總結(jié)大概常用的方法就寫那么多,剩下的看自己實際需要再去了解。
解決Node回調(diào)地獄的不止有Promise,還有Generator和ES7提出的Async實現(xiàn)。
方法不在多,而在于精。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/89197.html
摘要:就算改變已經(jīng)發(fā)生了,你再對對象添加回調(diào)函數(shù),也會立即得到這個結(jié)果。有了對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調(diào)函數(shù)。但是在這里,會得到這樣的結(jié)果關(guān)于是用于指定發(fā)生錯誤時的回調(diào)函數(shù)。 看了很多關(guān)于promise的文章,此篇文章做以總結(jié)。由于Javascript是一種單線程的語言,所有的代碼必須按照所謂的自上而下的順序來執(zhí)行。本特性帶來的問題就是,一些將來的、未...
摘要:上代碼異步執(zhí)行成功的構(gòu)造函數(shù)接收一個函數(shù)參數(shù),并傳入兩個參數(shù),分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù)。第一個回調(diào)函數(shù)是對象的狀態(tài)變?yōu)闀r調(diào)用,第二個回調(diào)函數(shù)是對象的狀態(tài)變?yōu)闀r調(diào)用。 這篇文章只解決三個問題。什么是promise? promise有什么用?promise怎么用? 1.什么是promise? 對于ES6來說,就是一個構(gòu)造函數(shù),可以用new Prom...
摘要:的翻譯文檔由的維護很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:函數(shù)的關(guān)鍵字的作用是停止執(zhí)行退出函數(shù)暫停執(zhí)行,等待方法調(diào)用停止執(zhí)行,可自行恢復(fù)執(zhí)行答案解析函數(shù)可以有很多個。簡答題說出至少個的新特性,并簡述它們的作用。簡答題答關(guān)鍵字,用于聲明只在塊級作用域起作用的變量。對象,更合理規(guī)范地處理異步操作。 通過對ES6系列文章的學(xué)習(xí),相信大家對ES6已結(jié)有一定程度的了解。 所以本節(jié)的目的在于通過測試,便于讓大家了解在學(xué)習(xí)中的知識掌握情況,查缺補漏,一步一...
摘要:周五就想寫這篇文章,但是無奈花花世界的誘惑太多就一直拖到了今天,自責(zé)遍進入正題對象用于表示一個異步操作的最終狀態(tài)完成或失敗,以及其返回的值。 周五就想寫這篇文章,但是無奈花花世界的誘惑太多……就一直拖到了今天,自責(zé)1e4遍;進入正題Promise: Promise 對象用于表示一個異步操作的最終狀態(tài)(完成或失?。约捌浞祷氐闹?。 上為MDNPromise的定義;ES6規(guī)定Promis...
閱讀 1010·2023-04-25 14:45
閱讀 2792·2021-09-30 09:59
閱讀 3134·2021-09-22 15:48
閱讀 2432·2019-08-30 15:55
閱讀 3488·2019-08-30 15:44
閱讀 553·2019-08-29 14:07
閱讀 3420·2019-08-26 13:45
閱讀 546·2019-08-26 11:31