閱讀目錄
創(chuàng)新互聯(lián)網(wǎng)站建設(shè)服務(wù)商,為中小企業(yè)提供成都網(wǎng)站設(shè)計、做網(wǎng)站服務(wù),網(wǎng)站設(shè)計,網(wǎng)站托管、服務(wù)器租用等一站式綜合服務(wù)型公司,專業(yè)打造企業(yè)形象網(wǎng)站,讓您在眾多競爭對手中脫穎而出創(chuàng)新互聯(lián)。
最近在看《你不知道的javascript中卷》,發(fā)覺作者花了基本一半的篇幅去講異步和promise,覺得有必要總結(jié)一下。
其實本文的目的是想手寫一個Promise的,無奈總結(jié)著總結(jié)著發(fā)覺篇幅有點長,因此只好一分為二,先介紹promise的用法,知道怎么用,我們才知道怎么寫,所以把手寫一個promise的任務(wù)放到了下一篇文章當(dāng)中。
當(dāng)然,網(wǎng)上有很多關(guān)于promise的文章,都可以參考參考,有誤之處,歡迎之處。
什么是Prmoise
promise是ES6新增的一個特征,它已被列入ES6的正式規(guī)范中
Promise對象可以理解為一次執(zhí)行的異步操作,使用promise對象之后可以使用一種鏈?zhǔn)秸{(diào)用的方式來組織代碼;讓代碼更加的直觀。也就是說,有了Promise對象,就可以將異步操作以同步的操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)。
示例:未使用promise,回調(diào)必須層層嵌套
$.ajax(url1, function(data1){ // do something... $.ajax(url2, function(data2){ // do something... $.ajax(url3, function(data3){ // do something... done(data3); // 返回數(shù)據(jù) }) }); });
如果有多個嵌套,導(dǎo)致代碼不夠直觀,而且如果幾個操作之前沒有前后順序之分,需要等待上一個操作完成才可以進(jìn)行下一個操作,造成不必要的等待
promise就是為了解決這些問題而產(chǎn)生的。
Promise對象的特點:
1、對象的狀態(tài)不受外界影響。
Promise對象代表一個異步操作,有三種狀態(tài)
其中pending為初始狀態(tài),fulfilled和rejected為結(jié)束狀態(tài)(結(jié)束狀態(tài)表示promise的生命周期已結(jié)束)。
promise只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài).。
2、一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結(jié)果。
Promise對象的狀態(tài)改變,只有兩種可能:從Pending變?yōu)镽esolved和從Pending變?yōu)镽ejected
pending->fulfilled,pending->rejected。
只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會再變了,會一直保持這個結(jié)果
Promise對象的缺點:
1、無法取消Promise,一旦新建它就會立即執(zhí)行,無法中途取消。
2、如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯誤,不會反應(yīng)到外部。
3、當(dāng)處于Pending狀態(tài)時,無法得知目前進(jìn)展到哪一個階段(剛剛開始還是即將完成)。
promise兼容性
除了IE這種古老的瀏覽器和一些低版本的安卓外,現(xiàn)代瀏覽器支持還是挺好的,所以我們可以在谷歌的控制臺直接測試我們的代碼
Promise的使用
先提前說明一下,下面的代碼示例,都可以復(fù)制到谷歌的控制臺就行測試??!
1、基本用法:
(1)、首先我們new一個Promise,將Promise實例化
(2)、然后在實例化的promise可以傳兩個參數(shù),一個是成功之后的resolve,一個是失敗之后的reject
(3)、Promise實例生成以后,可以用then方法分別指定Resolved狀態(tài)和Reject狀態(tài)的回調(diào)函數(shù)
代碼如下:
var promise = function(isReady){ return new Promise(function(resolve, reject){ // do somthing, maybe async if (isReady){ return resolve('hello world'); } else { return reject('failure'); } }); } //Promise實例生成以后,可以用then方法分別指定Resolved狀態(tài)和Reject狀態(tài)的回調(diào)函數(shù)。 promise(true).then(function(value){ // success,這里是resolve的回調(diào)函數(shù) console.log(value); //hello world }, function(err){ // failure,這里是reject的回調(diào)函數(shù) console.log(err) })
上述代碼是執(zhí)行成功,返回hello world,如果想測試一下失敗后的返回值,可以在promise(true).then...這里改為 promise(false).then...即可
2、鏈?zhǔn)讲僮?/strong>
也許你會說,Promise只是簡化層層回調(diào)的寫法而已吧,其實不然,它的精髓是通過維護狀態(tài)、傳遞狀態(tài)的方式來使回調(diào)方式能夠及時的調(diào)用,因此,相比于callback,它更靈活,更簡單。下面我們來看看Promise的鏈?zhǔn)讲僮鳎?/p>
makePromise1() .then(function(value){ console.log(value); return makePromise2(); }) .then(function(value){ console.log(value); return makePromise3(); }) .then(function(value){ console.log(value); }); function makePromise1(){ var p = new Promise(function(resolve, reject){ //異步操作 setTimeout(function(){ console.log('異步任務(wù)1'); resolve('異步任務(wù)1傳過來的值'); }, 2000); }); return p; } function makePromise2(){ var p = new Promise(function(resolve, reject){ //異步操作 setTimeout(function(){ console.log('異步任務(wù)2'); resolve('異步任務(wù)2傳過來的值'); }, 2000); }); return p; } function makePromise3(){ var p = new Promise(function(resolve, reject){ //異步操作 setTimeout(function(){ console.log('異步任務(wù)3'); resolve('異步任務(wù)3傳過來的值'); }, 2000); }); return p; }
上面的代碼中,我們有三個異步操作,makePromise1,makePromise2,makePromise3。其中第二個和第三個依次執(zhí)行,也就是上一個操作完成之后才可以進(jìn)行。
輸出的值為:
異步任務(wù)1 異步任務(wù)1傳過來的值 異步任務(wù)2 異步任務(wù)2傳過來的值 異步任務(wù)3 異步任務(wù)3傳過來的值
3、Promise的catch方法
var promise = function(isReady){ return new Promise(function(resolve, reject){ // do somthing, maybe async if (isReady){ return resolve('hello world'); } else { return reject('failure'); } }); } promise(true) .then(function(value){ console.log('resolved'); console.log(value); console.log(haha); //此處的haha未定義 }) .catch(function(error){ console.log('rejected'); console.log(error); });
catch 方法是 then(onFulfilled, onRejected) 方法當(dāng)中 onRejected 函數(shù)的一個簡單的寫法,也就是說可以寫成 then(fn).catch(fn),相當(dāng)于 then(fn).then(null, fn)
使用 catch 的寫法比一般的寫法更加清晰明確,其實可以類比成try/catch,這樣,其中有報錯的地方不會阻塞運行。比如定義了一個未定義haha,正常來說它上面的代碼也不會運行,因為被這個報錯阻塞了,有了catch,它上面的代碼可以正常運行下去:
控制臺打印出來的東西:
resolved hello world rejected ReferenceError: haha is not defined(…)
4、promise.all方法
Promise.all 可以接收一個元素為 Promise 對象的數(shù)組作為參數(shù),當(dāng)這個數(shù)組里面所有的 Promise 對象都變?yōu)?resolve 時,該方法才會返回。
代碼示例:
var p1 = new Promise(function (resolve) { setTimeout(function () { resolve("第一個promise"); }, 3000); }); var p2 = new Promise(function (resolve) { setTimeout(function () { resolve("第二個promise"); }, 1000); }); Promise.all([p1, p2]).then(function (result) { console.log(result); // ["第一個promise", "第二個promise"] });
上面的代碼中,all接收一個數(shù)組作為參數(shù),p1,p2是并行執(zhí)行的,等兩個都執(zhí)行完了,才會進(jìn)入到then,all會把所有的結(jié)果放到一個數(shù)組中返回,所以我們打印出我們的結(jié)果為一個數(shù)組。
值得注意的是,雖然p2的執(zhí)行順序比p1快,但是all會按照參數(shù)里面的數(shù)組順序來返回結(jié)果。all的使用場景類似于,玩游戲的時候,需要提前將游戲需要的資源提前準(zhǔn)備好,才進(jìn)行頁面的初始化。
5、promise.race方法
race的中文意思為賽跑,也就是說,看誰跑的快,跑的快的就贏了。因此,promise.race也是傳入一個數(shù)組,但是與promise.all不同的是,race只返回跑的快的值,也就是說result返回比較快執(zhí)行的那個。
var p1 = new Promise(function (resolve) { setTimeout(function () { console.log(1); resolve("第一個promise"); }, 3000); }); var p2 = new Promise(function (resolve) { setTimeout(function () { console.log(2); resolve("第二個promise"); }, 1000); }); Promise.race([p1, p2]).then(function (result) { console.log(result); }); // 結(jié)果: // 2 // 第二個promise // 1
可以看到,傳的值中,只有p2的返回了,但是p1沒有停止,依然有執(zhí)行。
race的應(yīng)用場景為,比如我們可以設(shè)置為網(wǎng)路請求超時。寫兩個promise,如果在一定的時間內(nèi)如果成功的那個我們沒有執(zhí)行到,我們就執(zhí)行失敗的那個,這里不再舉例子,可以看看阮一峰的ES入門。
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持創(chuàng)新互聯(lián)!
分享標(biāo)題:淺談JavaScript中promise的使用
網(wǎng)站網(wǎng)址:http://jinyejixie.com/article40/ijoheo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊、微信公眾號、網(wǎng)站改版、企業(yè)網(wǎng)站制作、外貿(mào)建站、App設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)