網(wǎng)上也有很多關(guān)于promise的講解歌径,但感覺都停留在理論層面毁嗦,對(duì)于讀者來(lái)說(shuō),看了一遍回铛,似乎已經(jīng)全部明白了狗准,但真要用起來(lái),發(fā)現(xiàn)還是無(wú)從下手茵肃。因此腔长,本文旨在用人話為小伙伴們解釋一下promise到底真正怎么用。
最近的項(xiàng)目里包含了大量的表單交互验残,必然免不了各種異步請(qǐng)求捞附,promise使用相當(dāng)頻繁。我想您没,是時(shí)候來(lái)與小伙伴們分享一下我遇到的各種promise的坑了鸟召。
promise干嘛用的?----一般用于異步操作氨鹏。
為什么能用來(lái)異步操作欧募?----因?yàn)槟艿纫粋€(gè)函數(shù)執(zhí)行完之后執(zhí)行下一個(gè)函數(shù)操作。
懂了嗎仆抵?----懂了
那好跟继,用一個(gè)我看看----額种冬,那個(gè)。还栓。到底怎么寫來(lái)著碌廓。。
你不是都懂了嗎剩盒?----是啊,道理我都懂啊慨蛙,但為什么就是不會(huì)用呢辽聊。。
哈哈期贫,這就是我最初使用promise的深刻感受跟匆,明明那些概念都懂,語(yǔ)法也并不復(fù)雜通砍,可就是實(shí)際用的時(shí)候用不出來(lái)玛臂。如果你也有這種感受,那么封孙,恭喜你迹冤,來(lái)對(duì)地方了,跟著我繼續(xù)探索promise的秘密吧虎忌!
promise和then的配套使用
我們來(lái)想象這么一個(gè)生活情境:
開學(xué)了泡徙,幼兒園里的小朋友們排排坐,老師說(shuō):小朋友們膜蠢,讓我們來(lái)介紹自己的名字好不好呀堪藐,那么,從第一排的小紅開始挑围,依次往下介紹礁竞,好,我們開始吧杉辙!
小紅站起來(lái)說(shuō)模捂,大家好,我叫小紅奏瞬,
接著小強(qiáng)站起來(lái)說(shuō)枫绅,大家好,我叫小強(qiáng)
硼端。
并淋。
接著,輪到小明了珍昨,小明有個(gè)缺點(diǎn)县耽,就是一緊張就口吃句喷,只聽他紅著臉,站起來(lái)說(shuō):大兔毙。唾琼。大瓢娜。递览。大缰犁。禾酱。大堡掏。昭雌。家图毕。盹舞。好叙量。倡蝙。好。绞佩。
還沒說(shuō)完呢寺鸥,后面的急性子小剛就站了起來(lái),說(shuō):大家好品山,我叫小剛
說(shuō)完胆建,小剛后面的同學(xué)就接著站了起來(lái),繼續(xù)介紹自己谆奥。
最后眼坏,最后一排的同學(xué)也介紹完自己,坐下去了酸些。此時(shí)宰译,到家聽到小明的聲音:我叫。魄懂。叫沿侈。。叫市栗。缀拭。。叫填帽。蛛淋。叫。篡腌。
此時(shí)褐荷,老師也不耐煩了,說(shuō):行了嘹悼,小明叛甫,坐下吧
可憐的小明层宫,就這樣,連一個(gè)自我介紹都沒有完成其监。萌腿。。
好了抖苦,親毁菱,記住上面的故事了嗎?我們開始學(xué)習(xí)promise锌历。本來(lái)大家都好好的鼎俘,按順序自我介紹,挺好辩涝。但畢竟人生不如意十之八九,誰(shuí)能想到小明有些口吃呢勘天,所以小剛就搶著自我介紹了怔揩,你可能想說(shuō),這都怪小剛脯丝,可人家小剛還委屈呢商膊,老師說(shuō)的,按照座位來(lái)的宠进,既然小明已經(jīng)開始自我介紹了晕拆,那我就開始嘛,誰(shuí)知道他這么慢呢材蹬。
對(duì)实幕,小明就是這個(gè)異步操作,異步請(qǐng)求和接受服務(wù)器相應(yīng)都是需要時(shí)間的堤器,但是人家正常的js程序不管這些昆庇,一條語(yǔ)句執(zhí)行了,下一條語(yǔ)句就會(huì)接著執(zhí)行闸溃,不會(huì)去管上一條語(yǔ)句又沒有完成整吆,程序員你也沒說(shuō)要必須等上一條語(yǔ)句執(zhí)行完才能執(zhí)行下一條啊。
這樣的問題在哪里呢辉川,問題在最后表蝙,老師統(tǒng)計(jì)班上同學(xué)姓名的時(shí)候,會(huì)直接把小明漏掉乓旗,因?yàn)榻y(tǒng)計(jì)的時(shí)候府蛇,他都沒有自我介紹完啊寸齐!也就是說(shuō)欲诺,你后面的語(yǔ)句需要用到前面異步的返回值的時(shí)候抄谐,就會(huì)接收不到!
故事還沒完呢扰法,接下來(lái)聽第二段:
第二年蛹含,小明班上換了一個(gè)班主任,這回小明學(xué)聰明了塞颁,提前就跟老師說(shuō)明了他的情況浦箱,于是老師想了個(gè)辦法。
老師說(shuō)祠锣,同學(xué)們酷窥,我們今年的自我介紹,換一種方式伴网,每一位同學(xué)在自我介紹之前蓬推,必須要先說(shuō)出前一位同學(xué)的名字,才能進(jìn)行自我介紹澡腾,這樣小剛就算再性急沸伏,也必須要等小明自我介紹完了才能開始自我介紹。
多么聰明的老師啊动分,這樣毅糟,任何同學(xué),都能做完一個(gè)完整的自我介紹了澜公!
老師的做法姆另,就是promise。后一個(gè)同學(xué)必須要等錢一個(gè)同學(xué)說(shuō)完坟乾,因?yàn)樗枰耙粋€(gè)同學(xué)的名字迹辐。來(lái)看promise的語(yǔ)法:
new Promise((resolve,reject)=>{
// dosomething(異步操作);
resolve(value)
})
把老師的做法翻譯成js語(yǔ)句就是這樣:
var m=new Promise((resolve,reject)=>{
console.log('小明開始自我介紹')
setTimeout(()=>{//用定時(shí)器模擬的異步操作(小明口吃)
var name='小明'
resolve(name)
},3000)
})
m.then(model=>{
var preName=model
var name='小剛'
console.log(preName)
console.log(name)
})
執(zhí)行結(jié)果如下:
你會(huì)發(fā)現(xiàn),不光是小明在等待了3秒后才打印出來(lái)糊渊,小剛也一樣是等待了3秒后才打印出來(lái)右核,這充分說(shuō)明了promise的特點(diǎn),同時(shí)我都不用再解釋渺绒,相信then的用法相信小伙伴們也能很輕易的學(xué)會(huì)了贺喝!
Promise.all的應(yīng)用場(chǎng)合
接下來(lái),說(shuō)說(shuō)Promise.all的應(yīng)用場(chǎng)合宗兼,同樣躏鱼,上故事:
開學(xué)第二天,老師需要統(tǒng)計(jì)學(xué)生們的個(gè)人信息殷绍,于是讓班長(zhǎng)小紅給每人發(fā)了一張個(gè)人信息表染苛,讓他們填寫,并囑咐她,一定要等所有的同學(xué)都填完了茶行,再收上來(lái)躯概。小紅心里偷偷的笑了,肯定老師已經(jīng)知道小華寫字特別慢了畔师。娶靡。
天啊,這到底是怎樣一個(gè)班級(jí)看锉,口吃的姿锭、寫字慢的。伯铣。呻此。為老師默哀一秒鐘。腔寡。焚鲜。
咳咳,說(shuō)正事放前。其實(shí)老師的囑咐恃泪,便是Promise.all的做法,Promise.all語(yǔ)法如下:
Promise.all(arr)
arr是一個(gè)包含Promise對(duì)象元素的數(shù)組犀斋,可能這么說(shuō)還是有點(diǎn)抽象,那接下來(lái)把老師的做法翻譯成js:
var xiaoming=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaoming',age:'5'}
resolve(info)
},2000)
})
var xiaogang=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaogang',age:'6'}
resolve(info)
},1000)
})
var xiaohua=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaohua',age:'7'}
resolve(info)
},5000)
})
var arr=[xiaoming,xiaogang,xiaohua]
Promise.all(arr).then(model=>{
console.log(model)
})
結(jié)果如你所料情连,在等待了5秒后叽粹,控制臺(tái)打印出了三個(gè)人的信息:
Promise.all的用法也就一目了然了,它會(huì)讓多個(gè)互不影響的Promise里的語(yǔ)句同時(shí)執(zhí)行却舀,等待所有的Promise語(yǔ)句全部執(zhí)行完虫几,然后執(zhí)行then里的操作,返回給then的model是所有Promise里的resolve的值組成的一個(gè)數(shù)組挽拔。
promise的異常處理
同志們辆脸,接下來(lái),嘿嘿嘿螃诅,繼續(xù)講故事:
在填寫個(gè)人信息的時(shí)候啡氢,小智的通知看到他填的年齡是8歲,于是指著他說(shuō):哈哈哈术裸,你個(gè)智障倘是,8歲還讀幼兒園。袭艺。搀崭。小智惱羞成怒,和同桌大打了一架猾编,打架中途瘤睹,個(gè)人信息表也被同桌給撕了升敲。這下子,班長(zhǎng)小紅苦惱了轰传,老師可是說(shuō)驴党,要等每個(gè)人都寫完再把他們所有的信息表收上來(lái),這可怎么辦啊绸吸。鼻弧。。
好了锦茁,我們暫且先不要管這個(gè)班里為什么會(huì)有這么多奇葩攘轩。我們來(lái)看邏輯,本來(lái)異步請(qǐng)求正常執(zhí)行完码俩,接下來(lái)就執(zhí)行then里的resolve度帮,那現(xiàn)在如果向服務(wù)器請(qǐng)求失敗了,又會(huì)怎么樣呢稿存,總不能還是執(zhí)行吧笨篷,直接看代碼:
var xiaozhi=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaozhi',age:'8'}
var reason='打架,小智的信息表被撕了'
if(reason){
info=null
reject(reason)
}else{
resolve(info)
}
},5000)
})
xiaozhi.then(model=>{
console.log(model)
},error=>{
console.log('提交個(gè)人信息表失敗')
console.log('原因是'+error)
})
這段代碼執(zhí)行結(jié)果如下:
小智因?yàn)檫@個(gè)事情,被老師狠狠的批評(píng)了一頓瓣履,他不禁想率翅,如果時(shí)光能夠倒流,當(dāng)初沒有打這個(gè)架該多好啊袖迎。小伙伴們冕臭,你應(yīng)該明白我的意思了,不打架燕锥,reason就是undefined,就會(huì)進(jìn)入else里的語(yǔ)句辜贵,就能正常的輸出給then的model了。實(shí)際情況正是如此归形,你很難保證你的請(qǐng)求就一定能夠成功響應(yīng)托慨,如果沒有成功請(qǐng)求到數(shù)據(jù),你就應(yīng)該攔住它暇榴,執(zhí)行請(qǐng)求失敗的情況的語(yǔ)句厚棵。
可能有的小伙伴會(huì)錯(cuò)誤的理解為,失敗那不就是語(yǔ)句執(zhí)行錯(cuò)誤嗎蔼紧?這里一定要主要窟感,這里的失敗是指異步請(qǐng)求的失敗,并不是js語(yǔ)句的執(zhí)行失敗歉井。換句話說(shuō)柿祈,這里的失敗,是你自己定義的失敗,如果你非要把請(qǐng)求成功定義為失敗躏嚎,那也會(huì)照樣進(jìn)入reject蜜自,而不會(huì)執(zhí)行resolve。
Promise.all的異常處理
Promise.all的異常處理是什么樣子呢卢佣,看代碼:
var xiaoming=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaoming',age:'5'}
resolve(info)
},2000)
})
var xiaogang=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaogang',age:'6'}
resolve(info)
},1000)
})
var xiaohua=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaohua',age:'7'}
resolve(info)
},5000)
})
var xiaozhi=new Promise((resolve,reject)=>{
setTimeout(()=>{
var info={name:'xiaozhi',age:'8'}
var reason='打架,小智的信息表被撕了'
if(reason){
info=null
reject(reason)
}else{
resolve(info)
}
},1000)
})
var arr=[xiaoming,xiaogang,xiaohua,xiaozhi]
Promise.all(arr).then(model=>{
console.log(model)
},error=>{
console.log('收上來(lái)失敗')
})
執(zhí)行結(jié)果如下:
1秒的時(shí)候重荠,打印出“收上來(lái)失敗”這句話,就好比
小紅把除了小智的其他人的信息表全部收上來(lái)了給老師虚茶,老師一看戈鲁,少了小智的,說(shuō):少了小智的嘹叫,重新發(fā)下去吧婆殿,這信息表不全,收上來(lái)我也不要罩扇。
看到了吧婆芦,Promise.all就是保證所有的Promise都是成功的,只要有一個(gè)失敗喂饥,它就執(zhí)行reject消约,并且其他的哪怕是成功的Promise結(jié)果也都全部舍棄。這叫员帮,一個(gè)都不能少或粮!
怎么樣,小伙伴們捞高,看了這篇文章被啼,是否如同剝開了Promise身上的那層薄紗,將她看了個(gè)仔細(xì)呢(咳咳棠枉,別想歪。泡挺。辈讶。)。