promise

promise是什么腰鬼?

1、主要用于異步計(jì)算

2塑荒、可以將異步操作隊(duì)列化,按照期望的順序執(zhí)行姜挺,返回符合預(yù)期的結(jié)果

3齿税、可以在對(duì)象之間傳遞和操作promise,幫助我們處理隊(duì)列

為什么會(huì)有promise炊豪?

為了避免界面凍結(jié)(任務(wù))

同步:假設(shè)你去了一家飯店凌箕,找個(gè)位置拧篮,叫來(lái)服務(wù)員,這個(gè)時(shí)候服務(wù)員對(duì)你說(shuō)牵舱,對(duì)不起我是“同步”服務(wù)員串绩,我要服務(wù)完這張桌子才能招呼你。那桌客人明明已經(jīng)吃上了芜壁,你只是想要個(gè)菜單礁凡,這么小的動(dòng)作,服務(wù)員卻要你等到別人的一個(gè)大動(dòng)作完成之后慧妄,才能再來(lái)招呼你顷牌,這個(gè)便是同步的問(wèn)題:也就是“順序交付的工作1234,必須按照1234的順序完成”塞淹。

異步:則是將耗時(shí)很長(zhǎng)的A交付的工作交給系統(tǒng)之后窟蓝,就去繼續(xù)做B交付的工作,饱普。等到系統(tǒng)完成了前面的工作之后运挫,再通過(guò)回調(diào)或者事件,繼續(xù)做A剩下的工作套耕。

AB工作的完成順序谁帕,和交付他們的時(shí)間順序無(wú)關(guān),所以叫“異步”箍铲。

異步操作的常見(jiàn)語(yǔ)法

事件監(jiān)聽(tīng)

document.getElementById('#start').addEventListener('click',start,false);functionstart(){// 響應(yīng)事件雇卷,進(jìn)行相應(yīng)的操作}// jquery on 監(jiān)聽(tīng)$('#start').on('click',start)

回調(diào)

// 比較常見(jiàn)的有ajax$.ajax('http://www.wyunfei.com/',{success(res){// 這里可以監(jiān)聽(tīng)res返回的數(shù)據(jù)做回調(diào)邏輯的處理}})// 或者在頁(yè)面加載完畢后回調(diào)$(function(){// 頁(yè)面結(jié)構(gòu)加載完成,做回調(diào)邏輯處理})

有了nodeJS之后...對(duì)異步的依賴進(jìn)一步加劇了

大家都知道在nodeJS出來(lái)之前PHP颠猴、Java关划、python等后臺(tái)語(yǔ)言已經(jīng)很成熟了,nodejs要想能夠有自己的一片天翘瓮,那就得拿出點(diǎn)自己的絕活:

無(wú)阻塞高并發(fā)贮折,是nodeJS的招牌,要達(dá)到無(wú)阻塞高并發(fā)異步是其基本保障

舉例:查詢數(shù)據(jù)從數(shù)據(jù)庫(kù)资盅,PHP第一個(gè)任務(wù)查詢數(shù)據(jù)调榄,后面有了新任務(wù),那么后面任務(wù)會(huì)被掛起排隊(duì)呵扛;而nodeJS是第一個(gè)任務(wù)掛起交給數(shù)據(jù)庫(kù)去跑每庆,然后去接待第二個(gè)任務(wù)交給對(duì)應(yīng)的系統(tǒng)組件去處理掛起,接著去接待第三個(gè)任務(wù)...那這樣子的處理必然要依賴于異步操作

異步回調(diào)的問(wèn)題:

之前處理異步是通過(guò)純粹的回調(diào)函數(shù)的形式進(jìn)行處理

很容易進(jìn)入到回調(diào)地獄中今穿,剝奪了函數(shù)return的能力

問(wèn)題可以解決缤灵,但是難以讀懂,維護(hù)困難

稍有不慎就會(huì)踏入回調(diào)地獄 - 嵌套層次深,不好維護(hù)

回調(diào)地獄

一般情況我們一次性調(diào)用API就可以完成請(qǐng)求腮出。

有些情況需要多次調(diào)用服務(wù)器API帖鸦,就會(huì)形成一個(gè)鏈?zhǔn)秸{(diào)用,比如為了完成一個(gè)功能胚嘲,我們需要調(diào)用API1作儿、API2、API3馋劈,依次按照順序進(jìn)行調(diào)用攻锰,這個(gè)時(shí)候就會(huì)出現(xiàn)回調(diào)地獄的問(wèn)題

promise

promise是一個(gè)對(duì)象,對(duì)象和函數(shù)的區(qū)別就是對(duì)象可以保存狀態(tài)侣滩,函數(shù)不可以(閉包除外)

并未剝奪函數(shù)return的能力口注,因此無(wú)需層層傳遞callback,進(jìn)行回調(diào)獲取數(shù)據(jù)

代碼風(fēng)格君珠,容易理解寝志,便于維護(hù)

多個(gè)異步等待合并便于解決

promise詳解

newPromise(function(resolve,reject){// 一段耗時(shí)的異步操作resolve('成功')// 數(shù)據(jù)處理完成// reject('失敗') // 數(shù)據(jù)處理出錯(cuò)}).then((res)=>{console.log(res)},// 成功(err)=>{console.log(err)}// 失敗)

resolve作用是,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸?pending 變?yōu)?resolved)策添,在異步操作成功時(shí)調(diào)用材部,并將異步操作的結(jié)果,作為參數(shù)傳遞出去唯竹;

reject作用是乐导,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤笆 保磸?pending 變?yōu)?rejected),在異步操作失敗時(shí)調(diào)用浸颓,并將異步操作報(bào)出的錯(cuò)誤物臂,作為參數(shù)傳遞出去。

promise有三個(gè)狀態(tài):

1产上、pending[待定]初始狀態(tài)

2棵磷、fulfilled[實(shí)現(xiàn)]操作成功

3、rejected[被否決]操作失敗

當(dāng)promise狀態(tài)發(fā)生改變晋涣,就會(huì)觸發(fā)then()里的響應(yīng)函數(shù)處理后續(xù)步驟仪媒;

promise狀態(tài)一經(jīng)改變,不會(huì)再變谢鹊。

Promise對(duì)象的狀態(tài)改變算吩,只有兩種可能:

從pending變?yōu)閒ulfilled

從pending變?yōu)閞ejected。

這兩種情況只要發(fā)生佃扼,狀態(tài)就凝固了偎巢,不會(huì)再變了。

最簡(jiǎn)單示例:

newPromise(resolve=>{setTimeout(()=>{resolve('hello')},2000)}).then(res=>{console.log(res)})

分兩次兼耀,順序執(zhí)行

newPromise(resolve=>{setTimeout(()=>{resolve('hello')},2000)}).then(val=>{console.log(val)//? 參數(shù)val = 'hello'returnnewPromise(resolve=>{setTimeout(()=>{resolve('world')},2000)})}).then(val=>{console.log(val)// 參數(shù)val = 'world'})

promise完成后then()

letpro=newPromise(resolve=>{setTimeout(()=>{resolve('hello world')},2000)})setTimeout(()=>{pro.then(value=>{console.log(value)// hello world})},2000)

結(jié)論:promise作為隊(duì)列最為重要的特性艘狭,我們?cè)谌魏我粋€(gè)地方生成了一個(gè)promise隊(duì)列之后挎扰,我們可以把他作為一個(gè)變量傳遞到其他地方臼婆。

假如在.then()的函數(shù)里面不返回新的promise家凯,會(huì)怎樣鳍贾?

.then()

1、接收兩個(gè)函數(shù)作為參數(shù)官撼,分別代表fulfilled(成功)和rejected(失敗)

2似谁、.then()返回一個(gè)新的Promise實(shí)例傲绣,所以它可以鏈?zhǔn)秸{(diào)用

3、當(dāng)前面的Promise狀態(tài)改變時(shí)巩踏,.then()根據(jù)其最終狀態(tài)秃诵,選擇特定的狀態(tài)響應(yīng)函數(shù)執(zhí)行

4、狀態(tài)響應(yīng)函數(shù)可以返回新的promise塞琼,或其他值菠净,不返回值也可以我們可以認(rèn)為它返回了一個(gè)null;

5彪杉、如果返回新的promise毅往,那么下一級(jí).then()會(huì)在新的promise狀態(tài)改變之后執(zhí)行

6、如果返回其他任何值派近,則會(huì)立即執(zhí)行下一級(jí).then()

.then()里面有.then()的情況

1攀唯、因?yàn)?then()返回的還是Promise實(shí)例

2、會(huì)等里面的then()執(zhí)行完渴丸,再執(zhí)行外面的

then嵌套

對(duì)于我們來(lái)說(shuō)侯嘀,此時(shí)最好將其展開(kāi),也是一樣的結(jié)果谱轨,而且會(huì)更好讀:

展開(kāi)增加可讀性

錯(cuò)誤處理

Promise會(huì)自動(dòng)捕獲內(nèi)部異常戒幔,并交給rejected響應(yīng)函數(shù)處理。

第一種錯(cuò)誤處理

第一種錯(cuò)誤處理

第二種錯(cuò)誤處理

第二種錯(cuò)誤處理

錯(cuò)誤處理兩種做法:

第一種:reject('錯(cuò)誤信息').then(() => {}, () => {錯(cuò)誤處理邏輯})

第二種:throw new Error('錯(cuò)誤信息').catch( () => {錯(cuò)誤處理邏輯})

推薦使用第二種方式碟嘴,更加清晰好讀溪食,并且可以捕獲前面所有的錯(cuò)誤(可以捕獲N個(gè)then回調(diào)錯(cuò)誤)

catch() + then()

第一種情況:

第一種情況

第一種情況 - 結(jié)果

結(jié)論:catch也會(huì)返回一個(gè)promise實(shí)例,并且是resolved狀態(tài)

第二種情況:

第二種情況

第二種情況結(jié)果

結(jié)論:拋出錯(cuò)誤變?yōu)閞ejected狀態(tài)娜扇,所以繞過(guò)兩個(gè)then直接跑到最下面的catch

Promise.all() 批量執(zhí)行

Promise.all([p1, p2, p3])用于將多個(gè)promise實(shí)例错沃,包裝成一個(gè)新的Promise實(shí)例,返回的實(shí)例就是普通的promise

它接收一個(gè)數(shù)組作為參數(shù)

數(shù)組里可以是Promise對(duì)象雀瓢,也可以是別的值枢析,只有Promise會(huì)等待狀態(tài)改變

當(dāng)所有的子Promise都完成,該P(yáng)romise完成刃麸,返回值是全部值得數(shù)組

有任何一個(gè)失敗醒叁,該P(yáng)romise失敗,返回值是第一個(gè)失敗的子Promise結(jié)果

//切菜functioncutUp(){console.log('開(kāi)始切菜。');varp=newPromise(function(resolve,reject){//做一些異步操作setTimeout(function(){console.log('切菜完畢把沼!');resolve('切好的菜');},1000);});returnp;}//燒水functionboil(){console.log('開(kāi)始燒水啊易。');varp=newPromise(function(resolve,reject){//做一些異步操作setTimeout(function(){console.log('燒水完畢!');resolve('燒好的水');},1000);});returnp;}Promise.all([cutUp(),boil()]).then((result)=>{console.log('準(zhǔn)備工作完畢');console.log(result);})

Promise.race() 類似于Promise.all() 饮睬,區(qū)別在于它有任意一個(gè)完成就算完成

letp1=newPromise(resolve=>{setTimeout(()=>{resolve('I\`m p1 ')},1000)});letp2=newPromise(resolve=>{setTimeout(()=>{resolve('I\`m p2 ')},2000)});Promise.race([p1,p2]).then(value=>{console.log(value)})

常見(jiàn)用法:

異步操作和定時(shí)器放在一起租谈,,如果定時(shí)器先觸發(fā)捆愁,就認(rèn)為超時(shí)割去,告知用戶;

例如我們要從遠(yuǎn)程的服務(wù)家在資源如果5000ms還沒(méi)有加載過(guò)來(lái)我們就告知用戶加載失敗

現(xiàn)實(shí)中的用法

回調(diào)包裝成Promise昼丑,他有兩個(gè)顯而易見(jiàn)的好處:

1呻逆、可讀性好

2、返回 的結(jié)果可以加入任何Promise隊(duì)列

實(shí)戰(zhàn)示例菩帝,回調(diào)地獄和promise對(duì)比:

/***

? 第一步:找到北京的id

? 第二步:根據(jù)北京的id -> 找到北京公司的id

? 第三步:根據(jù)北京公司的id -> 找到北京公司的詳情

? 目的:模擬鏈?zhǔn)秸{(diào)用咖城、回調(diào)地獄

***/// 回調(diào)地獄// 請(qǐng)求第一個(gè)API: 地址在北京的公司的id$.ajax({url:'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',success(resCity){letfindCityId=resCity.filter(item=>{if(item.id=='c1'){returnitem}})[0].id? ? ? ? ? $.ajax({//? 請(qǐng)求第二個(gè)API: 根據(jù)上一個(gè)返回的在北京公司的id “findCityId”,找到北京公司的第一家公司的idurl:'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',success(resPosition){letfindPostionId=resPosition.filter(item=>{if(item.cityId==findCityId){returnitem}})[0].id// 請(qǐng)求第三個(gè)API: 根據(jù)上一個(gè)API的id(findPostionId)找到具體公司胁附,然后返回公司詳情$.ajax({url:'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',success(resCom){letcomInfo=resCom.filter(item=>{if(findPostionId==item.id){returnitem}})[0]console.log(comInfo)}})}})}})

// Promise 寫(xiě)法// 第一步:獲取城市列表constcityList=newPromise((resolve,reject)=>{$.ajax({url:'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',success(res){resolve(res)}})})// 第二步:找到城市是北京的idcityList.then(res=>{letfindCityId=res.filter(item=>{if(item.id=='c1'){returnitem}})[0].idfindCompanyId().then(res=>{// 第三步(2):根據(jù)北京的id -> 找到北京公司的idletfindPostionId=res.filter(item=>{if(item.cityId==findCityId){returnitem}})[0].id// 第四步(2):傳入公司的idcompanyInfo(findPostionId)})})// 第三步(1):根據(jù)北京的id -> 找到北京公司的idfunctionfindCompanyId(){letaaa=newPromise((resolve,reject)=>{$.ajax({url:'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',success(res){resolve(res)}})})returnaaa}// 第四步:根據(jù)上一個(gè)API的id(findPostionId)找到具體公司酒繁,然后返回公司詳情functioncompanyInfo(id){letcompanyList=newPromise((resolve,reject)=>{$.ajax({url:'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',success(res){letcomInfo=res.filter(item=>{if(id==item.id){returnitem}})[0]console.log(comInfo)}})})}

作者:王云飛_小四_wyunfei

鏈接:http://www.reibang.com/p/1b63a13c2701

來(lái)源:簡(jiǎn)書(shū)

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)控妻,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處州袒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市弓候,隨后出現(xiàn)的幾起案子郎哭,更是在濱河造成了極大的恐慌,老刑警劉巖菇存,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夸研,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡依鸥,警方通過(guò)查閱死者的電腦和手機(jī)亥至,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)贱迟,“玉大人姐扮,你說(shuō)我怎么就攤上這事∫路停” “怎么了茶敏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)缚俏。 經(jīng)常有香客問(wèn)我惊搏,道長(zhǎng)贮乳,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任恬惯,我火速辦了婚禮向拆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酪耳。我一直安慰自己亲铡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布葡兑。 她就那樣靜靜地躺著,像睡著了一般赞草。 火紅的嫁衣襯著肌膚如雪讹堤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天厨疙,我揣著相機(jī)與錄音洲守,去河邊找鬼。 笑死沾凄,一個(gè)胖子當(dāng)著我的面吹牛梗醇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撒蟀,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼叙谨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了保屯?” 一聲冷哼從身側(cè)響起手负,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎姑尺,沒(méi)想到半個(gè)月后竟终,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡切蟋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年统捶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柄粹。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喘鸟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镰惦,到底是詐尸還是另有隱情迷守,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布旺入,位于F島的核電站兑凿,受9級(jí)特大地震影響凯力,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜礼华,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一咐鹤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧圣絮,春花似錦祈惶、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至棒搜,卻和暖如春疹蛉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背力麸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工可款, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人克蚂。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓闺鲸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親埃叭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摸恍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • //本文內(nèi)容起初摘抄于 阮一峰 作者的譯文,用于記錄和學(xué)習(xí)游盲,建議觀者移步于原文 概念: 所謂的Promise误墓,...
    曾經(jīng)過(guò)往閱讀 1,225評(píng)論 0 7
  • 去年6月份, ES2015正式發(fā)布(也就是ES6益缎,ES6是它的乳名)谜慌,其中Promise被列為正式規(guī)范。作為ES6...
    豬豬俠闖天下閱讀 943評(píng)論 0 0
  • ES6 Promise 用法講解 Promise是一個(gè)構(gòu)造函數(shù)莺奔,自己身上有all欣范、reject、resolve這幾...
    Marting424閱讀 271評(píng)論 1 0
  • Promise是一個(gè)構(gòu)造函數(shù)令哟,自己身上有all恼琼、reject、resolve這幾個(gè)眼熟的方法屏富,原型上有then晴竞、c...
    HJHA閱讀 284評(píng)論 0 0
  • 在ES6當(dāng)中添加了很多新的API其中很值得一提的當(dāng)然少不了Promise,因?yàn)镻romise的出現(xiàn)狠半,很輕松的就給開(kāi)...
    嘿_那個(gè)誰(shuí)閱讀 3,663評(píng)論 2 3