概述:
Promise是一個構(gòu)造函數(shù)粥谬,JS原生提供Promise對象系馆。
Promise?對象用于表示一個異步操作的最終狀態(tài)(完成或失斔と稀),以及該異步操作的結(jié)果值无畔。
Promise 是異步編程的一種解決方案啊楚,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大。
特點:
不同于老式的傳入回調(diào)浑彰,在應(yīng)用 Promise 時恭理,將會有以下特點:
1.Promise會放到微隊列中,因為他是異步執(zhí)行郭变,會插入到本輪事件循環(huán)的末尾颜价,所以會晚于同步代碼執(zhí)行。
2.通過 .then()形式添加的回調(diào)函數(shù)都會被調(diào)用诉濒,即便是在異步操作完成之后才被添加的函數(shù)周伦。
3.通過多次調(diào)用 .then(),可以添加多個回調(diào)函數(shù)未荒,它們會按照插入順序并且獨立運行专挪。
因此,Promise 最直接的好處就是鏈?zhǔn)秸{(diào)用。
狀態(tài):
pending: 初始狀態(tài)狈蚤,既不是成功困肩,也不是失敗狀態(tài)。
fulfilled: 意味著操作成功完成脆侮。
rejected: 意味著操作失敗锌畸。
語法:
Promise構(gòu)造函數(shù)接受一個函數(shù)作為參數(shù),先把這個函數(shù)叫做executor靖避。
executor是帶有?resolve?和?reject?兩個參數(shù)的函數(shù)?潭枣。Promise構(gòu)造函數(shù)執(zhí)行時立即調(diào)用executor?函數(shù),resolve?和?reject?兩個函數(shù)作為參數(shù)傳遞給executor(executor 函數(shù)在Promise構(gòu)造函數(shù)返回實例對象前被調(diào)用)幻捏。resolve?和?reject?函數(shù)被調(diào)用時盆犁,分別將promise的狀態(tài)改為fulfilled(完成)或rejected(失敗)篡九。executor 內(nèi)部通常會執(zhí)行一些異步操作谐岁,一旦異步操作執(zhí)行完畢(可能成功/失敗),要么調(diào)用resolve函數(shù)來將promise狀態(tài)改成fulfilled榛臼,要么調(diào)用reject?函數(shù)將promise的狀態(tài)改為rejected伊佃。如果在executor函數(shù)中拋出一個錯誤,那么該promise 狀態(tài)為rejected沛善。executor函數(shù)的返回值被忽略航揉。
實例方法:
Promise.prototype.then(fun1(x),fun2(x))
該方法接受兩個函數(shù)作為參數(shù),promise的狀態(tài)為成功時調(diào)用第一個參數(shù)金刁,失敗時調(diào)用第二個參數(shù)帅涂。也就是當(dāng)resolve函數(shù)被成功調(diào)用時,觸發(fā)then的第一個參數(shù)尤蛮,當(dāng)reject函數(shù)被調(diào)用時媳友,觸發(fā)then的第二個參數(shù)。
每個回調(diào)也都接受一個參數(shù)产捞,分別為resolve和reject函數(shù)被調(diào)用時傳入的參數(shù)醇锚。
then方法返回一個新的Promise對象,注意轧葛,是新的搂抒!
栗子:
當(dāng)我傳入1時艇搀,resolve執(zhí)行(只要它執(zhí)行了就代表成功了)尿扯,看下控制臺輸出:
邏輯分析:執(zhí)行promise ---> resolve函數(shù)執(zhí)行?---> then的第一個回調(diào)執(zhí)行?---> 返回一個新的promise對象 --->?then的第一個回調(diào)執(zhí)行
看下例是如何失敗的:
當(dāng)我傳入9999時,reject函數(shù)被調(diào)用(它被調(diào)用就代表失敗了)焰雕,看控制臺輸出:
邏輯分析:執(zhí)行promise ---> reject函數(shù)執(zhí)行?--->?then的第二個回調(diào)執(zhí)行?--->?返回一個新的promise對象?--->?then的第一個回調(diào)執(zhí)行
劃重點:
promise明明失敗了衷笋,為什么第二個then的第一個回調(diào)執(zhí)行而不是第二個呢?因為then返回的是一個新的promise對象矩屁,和被傳入9999執(zhí)行的函數(shù)返回的不是同一個promise辟宗。此時也就是說新的promise的狀態(tài)為成功爵赵,但如果第一個then的某個回調(diào)執(zhí)行后發(fā)生錯誤,第二個then的第二個回調(diào)就會調(diào)用了泊脐,因為這是新的promise失敗了空幻。
對于新人糾結(jié)的問題(就是本人):這tm成功失敗不就是if else控制的嗎?
見下例:
我擦容客?我干你大爺是什么鬼秕铛?見控制臺輸出:
邏輯分析:執(zhí)行promise ---> 報錯了!K跆簟但两! 默認(rèn)調(diào)用reject函數(shù),參數(shù)為拋出的錯誤對象 --->? then的第二個回調(diào)執(zhí)行?--->?返回一個新的promise對象?--->?then的第一個回調(diào)執(zhí)行
結(jié)論:發(fā)生錯誤會自動調(diào)用reject供置,傳入的參數(shù)是錯誤對象
Promise.prototype.catch(fun(x))
該方法接受一個函數(shù)作為參數(shù)谨湘,在失敗時調(diào)用,也就是當(dāng)reject函數(shù)被調(diào)用時觸發(fā)該方法芥丧。也就是說它也能接收promise的失敗狀態(tài)紧阔,并執(zhí)行回調(diào)函數(shù),回調(diào)的參數(shù)為reject函數(shù)被調(diào)用時的傳入的參數(shù)娄柳。見下例:
如果promise拋出錯誤寓辱,比如上面那個‘我是你大爺’,也會執(zhí)行catch
還有赤拒,如果then的回調(diào)發(fā)生錯誤秫筏,catch同樣執(zhí)行。
PS:catch后面接的then挎挖,回調(diào)函數(shù)內(nèi)的console.log輸出的內(nèi)容我手誤了这敬,你可以看成我接收到catch回調(diào)傳給我的參數(shù)是......
關(guān)于承若:
promise就是承若,說一不二蕉朵,何為說以不二崔涂?見下例:
當(dāng)resolve執(zhí)行,狀態(tài)就為成功始衅,此后狀態(tài)就不變了冷蚂,我們看到后面跟了一個我干你大爺,但是狀態(tài)沒變汛闸。這就是承若蝙茶。
我們發(fā)現(xiàn),控制臺第一個出現(xiàn)的是一個'promise',然后才是then的第一個回調(diào)執(zhí)行诸老。這就是此文一開始說的promise的特點隆夯。
Promise.all方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例,接受一個數(shù)組作為參數(shù)蹄衷,數(shù)組成員需要是promise對象忧额,若不是,會轉(zhuǎn)愧口。數(shù)組成員全部成功睦番,那么新Promise實例則成功,有一個失敗耍属,那就失敗抡砂。若成功,resolve的參數(shù)是一個數(shù)組恬涧,成員為數(shù)組中成員的成功結(jié)果注益。弱失敗,reject的參數(shù)就是失敗成員的結(jié)果溯捆。
Promise.race方法同樣是將多個 Promise 實例丑搔,包裝成一個新的 Promise 實例。只要有一個實例率先改變狀態(tài)提揍,新Promise的狀態(tài)就跟著改變啤月。那個率先改變的 Promise 實例的返回值,就傳遞給新Promise的回調(diào)函數(shù)劳跃。
Promise.resolve方法將參數(shù)轉(zhuǎn)為Promise對象谎仲。
1.如果參數(shù)是 Promise 實例,那么Promise.resolve將不做任何修改刨仑、原封不動地返回這個實例郑诺。
2.參數(shù)是一個thenable對象,Promise.resolve方法會將這個對象轉(zhuǎn)為 Promise 對象杉武,然后就立即執(zhí)行thenable對象的then方法辙诞。thenable的執(zhí)行結(jié)果會做為Promise對象的resolve的參數(shù)。見下例:
??如果參數(shù)是一個原始值轻抱,或者是一個不具有then方法的對象飞涂,則Promise.resolve方法返回一個新的 Promise 對象,狀態(tài)為resolved祈搜。參數(shù)為resolve的參數(shù)较店。
Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態(tài)為rejected容燕。注意梁呈,Promise.reject()方法的參數(shù),會原封不動地作為reject的理由缰趋,變成后續(xù)方法的參數(shù)捧杉。這一點與Promise.resolve方法不一致。
? ??
? ???? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????????????????????????????????????MDN
? ??????????????????????????????????????????????????????????????????????????????????????????????????MDN
? ??????????????????????????????????????????????????????????????????????????????????????????????????阮師傅