什么是Promise呢绑谣?
ES6中一個非常重要和好用的特性就是Promise
但是初次接觸Promise會一臉懵逼夜焦,這TM是什么東西捞稿?
看看官方或者一些文章對它的介紹和用法,也是一頭霧水荞胡。
Promise到底是做什么的呢妈踊?
Promise是異步編程的一種解決方案。
那什么時候我們會來處理異步事件呢泪漂?
一種很常見的場景應(yīng)該就是網(wǎng)絡(luò)請求了廊营。
我們封裝一個網(wǎng)絡(luò)請求的函數(shù),因為不能立即拿到結(jié)果萝勤,所以不能像簡單的3+4=7一樣將結(jié)果返回露筒。
所以往往我們會傳入另外一個函數(shù),在數(shù)據(jù)請求成功時敌卓,將數(shù)據(jù)通過傳入的函數(shù)回調(diào)出去慎式。
如果只是一個簡單的網(wǎng)絡(luò)請求,那么這種方案不會給我們帶來很大的麻煩。
但是瘪吏,當(dāng)網(wǎng)絡(luò)請求非常復(fù)雜時癣防,就會出現(xiàn)回調(diào)地獄。
OK掌眠,我以一個非忱俣ⅲ夸張的案例來說明。
我們來考慮下面的場景(有夸張的成分):
我們需要通過一個url1從服務(wù)器加載一個數(shù)據(jù)data1蓝丙,data1中包含了下一個請求的url2
我們需要通過data1取出url2刑枝,從服務(wù)器加載數(shù)據(jù)data2,data2中包含了下一個請求的url3
我們需要通過data2取出url3迅腔,從服務(wù)器加載數(shù)據(jù)data3,data3中包含了下一個請求的url4
發(fā)送網(wǎng)絡(luò)請求url4靠娱,獲取最終的數(shù)據(jù)data4
上面的代碼有什么問題嗎沧烈?
正常情況下,不會有什么問題像云,可以正常運行并且獲取我們想要的結(jié)果锌雀。
但是,這樣額代碼難看而且不容易維護迅诬。
我們更加期望的是一種更加優(yōu)雅的方式來進行這種異步操作腋逆。
promise的基本寫法
我們先來看看Promise最基本的語法。
這里侈贷,我們用一個定時器來模擬異步事件:
假設(shè)下面的data是從網(wǎng)絡(luò)上1秒后請求的數(shù)據(jù)
console.log就是我們的處理方式惩歉。
這是我們過去的處理方式,我們將它換成Promise代碼
這個例子會讓我們感覺脫褲放屁俏蛮,多此一舉
首先撑蚌,下面的Promise代碼明顯比上面的代碼看起來還要復(fù)雜。
其次搏屑,下面的Promise代碼中包含的resolve争涌、reject、then辣恋、catch都是些什么東西亮垫?
我們先不管第一個復(fù)雜度的問題,因為這樣的一個屁大點的程序根本看不出來Promise真正的作用伟骨。
定時器異步事件解析
我們先來認(rèn)認(rèn)真真的讀一讀這個程序到底做了什么饮潦?
new Promise很明顯是創(chuàng)建一個Promise對象
小括號中((resolve, reject) => {})也很明顯就是一個函數(shù),而且我們這里用的是之前剛剛學(xué)習(xí)過的箭頭函數(shù)携狭。
但是resolve, reject它們是什么呢害晦?
我們先知道一個事實:在創(chuàng)建Promise時,傳入的這個箭頭函數(shù)是固定的(一般我們都會這樣寫)
resolve和reject它們兩個也是函數(shù),通常情況下壹瘟,我們會根據(jù)請求數(shù)據(jù)的成功和失敗來決定調(diào)用哪一個鲫剿。
成功還是失敗稻轨?
如果是成功的灵莲,那么通常我們會調(diào)用resolve(messsage),這個時候殴俱,我們后續(xù)的then會被回調(diào)政冻。
如果是失敗的,那么通常我們會調(diào)用reject(error)线欲,這個時候明场,我們后續(xù)的catch會被回調(diào)。
OK李丰,這就是Promise最基本的使用了苦锨。
Promise三種狀態(tài)
首先, 當(dāng)我們開發(fā)中有異步操作時, 就可以給異步操作包裝一個Promise
異步操作之后會有三種狀態(tài)
我們一起來看一下這三種狀態(tài):
pending:等待狀態(tài),比如正在進行網(wǎng)絡(luò)請求趴泌,或者定時器沒有到時間舟舒。
fulfill:滿足狀態(tài),當(dāng)我們主動回調(diào)了resolve時嗜憔,就處于該狀態(tài)秃励,并且會回調(diào).then()
reject:拒絕狀態(tài),當(dāng)我們主動回調(diào)了reject時吉捶,就處于該狀態(tài)夺鲜,并且會回調(diào).catch()
鏈?zhǔn)秸{(diào)用簡寫
簡化版代碼:
如果我們希望數(shù)據(jù)直接包裝成Promise.resolve,那么在then中可以直接返回數(shù)據(jù)
注意下面的代碼中呐舔,我講return Promise.resovle(data)改成了return data
結(jié)果依然是一樣的