ES6 — Promise基础用法详解(resolve、reject、then、catch,all,)
ES6 — Promise基礎(chǔ)用法詳解
Promise 是一個(gè)構(gòu)造函數(shù),它自身?yè)碛衋ll、reject、resolve這幾個(gè)眼熟的方法,
原型上有then、catch等同樣熟悉的方法。
所以,在開始一個(gè)Promise的時(shí)候,先new一個(gè)吧:
Promise是一個(gè)構(gòu)造函數(shù),接受一個(gè)回調(diào)函數(shù)作為參數(shù),回調(diào)函數(shù)的參數(shù)是resolve、reject。分別表示異步操作執(zhí)行成功后的回調(diào)函數(shù)和異步操作執(zhí)行失敗后的回調(diào)函數(shù)。其實(shí)這里用“成功”和“失敗”來(lái)描述并不準(zhǔn)確,按照標(biāo)準(zhǔn)來(lái)講,resolve是將Promise的狀態(tài)置為fullfiled,reject是將Promise的狀態(tài)置為rejected。不過(guò)在我們開始階段可以先這么理解,后面再細(xì)究概念。
在上面的代碼中,我們執(zhí)行了一個(gè)異步操作,也就是setTimeout,1秒后,輸出“執(zhí)行完成”,并且調(diào)用resolve方法。
注意!我只是new了一個(gè)對(duì)象,并沒(méi)有調(diào)用它,我們傳進(jìn)去的函數(shù)就已經(jīng)執(zhí)行了,這是需要注意的一個(gè)細(xì)節(jié)。所以我們用Promise的時(shí)候一般是包在一個(gè)函數(shù)中,在需要的時(shí)候去運(yùn)行這個(gè)函數(shù),如:
function runAsync() {let p = new Promise((resolve, reject)=> {setTimeout(()=> {console.log('執(zhí)行完成');resolve(123);}, 1000)})return p; }runAsync()這時(shí)候你應(yīng)該有個(gè)疑問(wèn):包裝這么一個(gè)函數(shù)有什么作用?
在我們包裝好的函數(shù)最后,會(huì)return出Promise對(duì)象 p,也就是說(shuō),執(zhí)行這個(gè)函數(shù)我們得到了一個(gè)Promise對(duì)象。Promise對(duì)象上有then、catch方法,這這個(gè)時(shí)候就可以用到它們了,看下面的代碼:
runAsync().then((result)=> {console.log(result);// 做其他操作 })在runAsync()的返回上直接調(diào)用then方法,then接收一個(gè)參數(shù),是函數(shù),并且會(huì)拿到我們?cè)趓unAsync中調(diào)用resolve時(shí)傳的的參數(shù)。運(yùn)行這段代碼,會(huì)在1秒后輸出“執(zhí)行完成”,緊接著輸出 “123” 。
這個(gè)時(shí)候你可能已經(jīng)明白了,原來(lái)then方法和我們平時(shí)寫的回調(diào)函數(shù)是一個(gè)道理,那我們直接寫回調(diào)函數(shù)就行了啊,為什么還要寫Promise呢?
確實(shí)在一些簡(jiǎn)單的場(chǎng)景下,回調(diào)函數(shù)已經(jīng)夠用,但是在現(xiàn)在前端的大環(huán)境和大發(fā)展的狀態(tài)下,經(jīng)常會(huì)出現(xiàn)回調(diào)地獄的情況,你可能需要在回調(diào)函數(shù)中,再繼續(xù)回調(diào)函數(shù),這樣下去就會(huì)很恐怖了。Promise就給我們帶來(lái)了更好的解決辦法。
Promise的優(yōu)勢(shì)在于,可以在then方法中繼續(xù)寫Promise對(duì)象并返回,然后繼續(xù)調(diào)用then來(lái)進(jìn)行回調(diào)操作。鏈?zhǔn)讲僮鞯挠梅?/h4>
看下面一個(gè)例子,多層回調(diào)時(shí)是怎么使用的:
function runAsync1() {var p = new Promise(function(resolve, reject) {setTimeout(function(){console.log('執(zhí)行完成1');resolve(1);}, 1000)})return p; }function runAsync2() {var p = new Promise(function(resolve, reject) {setTimeout(function(){console.log('執(zhí)行完成2');resolve(2);}, 1000)})return p; }function runAsync3() {var p = new Promise(function(resolve, reject) {setTimeout(function(){console.log('執(zhí)行完成3');resolve(3);}, 1000)})return p; }runAsync1().then(function(data) {console.log(data);return runAsync2(); }).then(function(data) {console.log(data);return runAsync3(); }).then(function(data) {console.log(data);return '直接返回?cái)?shù)據(jù)' }).then(function(data) {console.log(data); })在鏈?zhǔn)讲僮髦?#xff0c;當(dāng)一個(gè)Promise結(jié)束后,可以繼續(xù)返回一個(gè)新的Promise,在下一個(gè)then方法中繼續(xù)接收其返回的resolve。
在then方法中,你也可以直接return數(shù)據(jù)而不是Promise對(duì)象,在后面的then中就可以接收到數(shù)據(jù)了,看上面例子的最后一個(gè)。
reject的用法
說(shuō)完resolve ,就不得不說(shuō)reject,它們都是Promise自身的方法,簡(jiǎn)單來(lái)說(shuō),reject方法返回的是錯(cuò)誤信息,將Promise的狀態(tài)置為rejected,上面已經(jīng)說(shuō)過(guò)。
我們下面來(lái)看看具體的實(shí)現(xiàn):
function getNumber() {var p = new Promise(function(resolve, reject) {setTimeout(function(){var num = Math.ceil(Math.random()*10);if(num<5) {resolve(num)} else {reject('數(shù)字太大了')}}, 1000)});return p; } getNumber().then(function(data) {console.log('resolve')console.log(data);},function(reason) {console.log('reject')console.log(reason); })我們創(chuàng)建一個(gè)隨機(jī)1-10的數(shù),判斷大小,返回不同的resolve和reject。
首先我們可以在then方法中第二個(gè)參數(shù)來(lái)接收reject返回值。如果是大于5我們就會(huì)打印出數(shù)字太大了。
但是很多人之前都有接觸過(guò)Promise,知道還有一個(gè)catch的鏈?zhǔn)讲僮鞣椒āK部梢杂脕?lái)接收reject返回的信息。來(lái)看下面的代碼:
getNumber().then(function(data) {console.log('resolve');console.log(data);}).catch(function(reason) {console.log('reject');console.log(reason); })如果數(shù)字大于5就會(huì)打印 reject 6。
如果你在then中出現(xiàn)了錯(cuò)誤,也不會(huì)中斷程序的運(yùn)行,會(huì)在catch中打印出錯(cuò)誤信息:
getNumber().then(function(data) {console.log('resolve');console.log(data);console.log(somedata);}).catch(function(reason) {console.log('reject');console.log(reason); // ReferenceError: somedata is not defined})Promise.all()
簡(jiǎn)單來(lái)說(shuō),all的作用就是并行執(zhí)行多個(gè)異步操作,然后在最后一個(gè)異步程序結(jié)束后,再繼續(xù)下面的方法。
Promise // 用Promise.all來(lái)執(zhí)行,all接收一個(gè)數(shù)組參數(shù),里面的值最終都算返回Promise對(duì)象。.all([runAsync1(), runAsync2(), runAsync3()]).then(function(data) {console.log(data); // [1, 2, 3]});runAsync1(), runAsync2(), runAsync3()是我們上面中寫過(guò)的方法,不清楚的可以往上面翻一翻
根據(jù)上面的代碼我們可以看到,當(dāng)三個(gè)異步程序都執(zhí)行完成后,在then方法中一次返回一個(gè)data數(shù)組,是三個(gè)異步程序的返回值組成的集合。
方法很簡(jiǎn)單,那這個(gè)方法在現(xiàn)實(shí)中,有哪些實(shí)用的地方呢?
打開網(wǎng)頁(yè)時(shí),預(yù)先加載需要用到的各種資源如圖片、flash以及各種靜態(tài)文件。 所有的都加載完后,我們?cè)龠M(jìn)行頁(yè)面的初始化下面我們來(lái)看一個(gè)跟all相似,但是運(yùn)行過(guò)程不同的方法race。
Promise.race()
all方法的效果實(shí)際上是「誰(shuí)跑的慢,以誰(shuí)為準(zhǔn)執(zhí)行回調(diào)」,
那么相對(duì)的就有另一個(gè)方法「誰(shuí)跑的快,以誰(shuí)為準(zhǔn)執(zhí)行回調(diào)」,這就是race方法
race 的用法:
Promise.race([runAsync1(), runAsync2(), runAsync3()]).then(function(data){console.log(data); // 1})因?yàn)榈谝粋€(gè)方法先結(jié)束,所以程序就到在此運(yùn)行到then方法, 返回的 1
現(xiàn)實(shí)中 race 的使用也很多
可以用race給某個(gè)異步請(qǐng)求設(shè)置超時(shí)時(shí)間,并且在超時(shí)后執(zhí)行相應(yīng)的操作
/*---------- race 使用場(chǎng)景 ----------------*/// 請(qǐng)求某個(gè)圖片資源function requestImg() {var p = new Promise(function(resolve, reject) {var img = new Image();img.src = 'http://www.google.cn/landing/cnexp/google-search.png';img.onload = function() {resolve(img)}});return p;}// 延時(shí)函數(shù),用于給請(qǐng)求記時(shí)function timeout() {var p = new Promise(function(resolve, reject) {setTimeout(function() {reject('請(qǐng)求超時(shí)')}, 5000)});return p;}Promise.race([requestImg(), timeout()]).then(function(data) {console.log(data);document.body.appendChild(data);}).catch(function(reason) {console.log(reason);})如果你把圖片的url地址替換成一個(gè)不存在的地址,那么系統(tǒng)會(huì)報(bào)404的錯(cuò)誤,在接下來(lái)的catch中,會(huì)打印出錯(cuò)誤信息請(qǐng)求超時(shí)
總結(jié)
以上是生活随笔為你收集整理的ES6 — Promise基础用法详解(resolve、reject、then、catch,all,)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux系统下破解 Idea的步骤
- 下一篇: sqlServer sa账号被锁定