ES6——舉個例子理解Promise的原理和使用

1. Promise 之前

1.1 回調函數(shù)

回調函數(shù):把函數(shù)A當作參數(shù)傳遞給另一個函數(shù)B調用,那么A就是回調函數(shù)拘泞。
一些例子
具名回調

function 你有幾只狗(fn){
    fn('一只狗')
}
function 數(shù)狗(數(shù)量){
    console.log(數(shù)量)
}
你有幾只狗(數(shù)狗)   // 一只狗

匿名回調

function 你有幾只狗(fn){
    fn('一只狗')
}
你有幾只狗(function(數(shù)量){
console.log(數(shù)量) 
})         //  一只狗

常見的例子
jQuery中使用回調函數(shù)征炼,這里用的是匿名回調的方式

$("#btn").click(function(){
    console.log('點到我了')
})

1.2 回調地獄(回調缺點1)

回調地獄:指的是回調嵌套過多的情況肛炮,導致代碼很難被看懂厚棵。

let info = []
function 你有幾只狗(fn){
    fn('一只狗')
}
function 你有幾只貓(fn){
    fn('一只貓')
}
function 知道了(數(shù)量,callback){
    info.push(數(shù)量)
    console.log(info)
    if(callback){
        callback()
    }
}
// 開始調用 如果比這再多幾層烤宙,就不容易看懂了
你有幾只狗(function(狗數(shù)){
    console.log(狗數(shù))
    知道了(狗數(shù), function(){
        你有幾只貓(function(貓數(shù)){
            console.log(貓數(shù))
            知道了(貓數(shù))
        })
    })
})

1.3 不使用Promise二汛,如何解決

利用具名函數(shù)代替匿名函數(shù)

let info = []
function 你有幾只狗(fn){
    fn('一只狗')
}
function 你有幾只貓(fn){
    fn('一只貓')
}
function 知道了(數(shù)量,callback){
    info.push(數(shù)量)
    console.log(info)
    if(callback){
        callback()
    }
}
function 告訴你貓的個數(shù)(貓數(shù)){
    console.log(貓數(shù))
    知道了(貓數(shù))
}
function 繼續(xù)數(shù)(){
    你有幾只貓(告訴你貓的個數(shù))
}
function 告訴你狗的個數(shù)(狗數(shù)){
    console.log(狗數(shù))
    知道了(狗數(shù), 繼續(xù)數(shù))
}
你有幾只狗(告訴你狗的個數(shù))  // 好像也沒好到哪去婿崭。。肴颊。

1.4 回調方式各不相同氓栈,需要單獨記憶(回調缺點2)

readFile('C:\\1.txt',function (error, data) {   // node.js 讀取文件方法中的回調
        if(error) {
            console.log('成功')
            console.log(data.toString())
        } else {
            console.log('讀取文件失敗')
        }
    })

$.ajax({                              // jQuery中ajax方法中的回調
    url:'/2.txt'
    success: function(response) {
        console.log('成功')
    },
    error: function(){
        console.log('失敗')
    }
})

2. Promise 的目的

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調函數(shù)和事件——更合理和更強大婿着。它由社區(qū)最早提出和實現(xiàn)授瘦,ES6 將其寫進了語言標準,統(tǒng)一了用法竟宋,原生提供了Promise對象提完。

3. Promise 的原理

3.1 實現(xiàn)原理

ES6 規(guī)定,Promise對象是一個構造函數(shù)丘侠,用來生成Promise實例徒欣。通過在函數(shù)內部return 一個 Promise對象的實例,這樣就可以使用Promise的屬性和方法進行下一步操作了蜗字。

function 函數(shù)名(){
    return new Promise(function(resolve, reject) {
        // ... some code
          if (/* 異步操作成功 */){
            resolve(value);   // 異步操作成功時調用打肝,把結果作為參數(shù)傳遞出去
          } else {
            reject(error);     // 異步失敗時調用脂新,把錯誤作為參數(shù)傳遞出去
          }
        
    })
}

3.2 調用邏輯

3.2.png

S1和E1兩個都沒有報錯,執(zhí)行S2(resolve執(zhí)行粗梭,系統(tǒng)認為搞定了争便,沒報錯)
S1和E1任何一個有報錯,執(zhí)行E2(reject執(zhí)行断医,系統(tǒng)認為沒搞定滞乙,報錯了)

4. Promise 的使用

4.1 Promise 的屬性與方法

屬性
Promise.prototype 表示 Promise 構造器的原型
方法
Promise.prototype.then()
返回一個 Promise 。它最多需要有兩個參數(shù):Promise 的成功和失敗情況的回調函數(shù)鉴嗤。
Promise.prototype.catch()
返回一個Promise酷宵,并且處理拒絕的情況。等價于Promise.prototype.then(undefined, onRejected)
Promise.prototype.finally()
finally() 方法返回一個Promise躬窜,在執(zhí)行then()和catch()后浇垦,都會執(zhí)行finally指定的回調函數(shù)。避免同樣的語句需要在then()和catch()中各寫一次的情況荣挨。
Promise.all(iterable)
返回一個 Promise 實例男韧,iterable參數(shù)內所有的 promise 都resolved后,才回調完成resolve默垄。
Promise.race(iterable)
返回一個 promise 此虑,并伴隨著 promise對象解決的返回值或拒絕的錯誤原因, 只要 iterable 中有一個 promise 對象"解決(resolve)"或"拒絕(reject)"。
Promise.resolve()
返回一個以給定值解析后的Promise對象口锭。但如果這個值是個thenable(即帶有then方法)朦前,返回的promise會“跟隨”這個thenable的對象,采用它的最終狀態(tài)(指resolved/rejected/pending/settled)鹃操;如果傳入的value本身就是promise對象韭寸,則該對象作為Promise.resolve方法的返回值返回;否則以該值為成功狀態(tài)返回promise對象荆隘。
Promise.reject()
返回一個帶有拒絕原因reason參數(shù)的Promise對象恩伺。

4.2 將回調地獄中的例子,改寫為Promise的形式

4.2-1.png

可以看到使用 Promise后椰拒,邏輯變得非常直觀
寫得更完整一些
4.2-2.png

Promise套Promise時著角,也就是Promise鏈的時候——注意信息的傳遞
一個失敗的例子茬暇,當我們使用Promise鏈的時候髓梅,如果每一步都需要上一步的數(shù)據(jù)時追他,就需要傳參,成功通過resolve傳參缆毁,失敗通過reject傳參番川,如果忘記傳參,就得不到想要的結果。
resolve把成功的數(shù)據(jù)返回給下一個回調
reject把失敗的數(shù)據(jù)返回給下一個回調爽彤。
4.2-3.png

給這里的resolve傳一個參
4.2-4.png

改成失敗的例子
先不給reject傳參,如果失敗的話缚陷,下一個回調拿不到數(shù)據(jù)
4.2-5.png

給 reject傳參
4.2-6.png

我們可以看到适篙,即使是走的失敗回調,下一個成功回調還是執(zhí)行了箫爷,由于 不知道() 默認返回undefined, 相當于失敗已經(jīng)處理了嚷节,在成功和失敗都被處理的情況下,下一個回調會執(zhí)行的虎锚。
改成符合預期的硫痰,即失敗不調用。
4.2-7.png

失敗不調用的簡寫形式
4.2-8.png

上述情況執(zhí)行后 .then(除了狗呢)里面的成功回調沒有執(zhí)行窜护,我們增加一個失敗回調看看
4.2-9.png

同樣也可以返回 resolve,讓后面成功回調可以執(zhí)行
4.2-10.png

4.3 應用

加載圖片
將圖片的加載寫成一個Promise效斑,一旦加載完成,Promise的狀態(tài)就發(fā)生變化柱徙。

const preloadImage = function (path) {
  return new Promise(function (resolve, reject) {
    const image = new Image();
    image.onload  = resolve;
    image.onerror = reject;
    image.src = path;
  });
};

Generator 函數(shù)與 Promise 的結合(詳情見參考鏈接缓屠,阮一峰的教程)

5. 干掉Promise中的回調

5.1 await

成功的情況


5.1-1.png

失敗的情況
利用 try catch


5.1-2.png

await 配合 try catch使用,比較完整

6. 總結

能利用Promise對象护侮,把普通函數(shù)改成返回Promise的形式敌完,解決回調地獄的問題。
明白Promise的成功失敗調用邏輯羊初,可以靈活的進行調整滨溉。
理解核心知識,先用起來长赞,慢慢整合吸收知識晦攒。

7. 參考鏈接

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市得哆,隨后出現(xiàn)的幾起案子勤家,更是在濱河造成了極大的恐慌,老刑警劉巖柳恐,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伐脖,死亡現(xiàn)場離奇詭異,居然都是意外死亡乐设,警方通過查閱死者的電腦和手機讼庇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來近尚,“玉大人蠕啄,你說我怎么就攤上這事。” “怎么了歼跟?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵和媳,是天一觀的道長。 經(jīng)常有香客問我哈街,道長留瞳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任骚秦,我火速辦了婚禮她倘,結果婚禮上,老公的妹妹穿的比我還像新娘作箍。我一直安慰自己硬梁,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布胞得。 她就那樣靜靜地躺著荧止,像睡著了一般。 火紅的嫁衣襯著肌膚如雪阶剑。 梳的紋絲不亂的頭發(fā)上罩息,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音个扰,去河邊找鬼瓷炮。 笑死,一個胖子當著我的面吹牛递宅,可吹牛的內容都是我干的娘香。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼办龄,長吁一口氣:“原來是場噩夢啊……” “哼烘绽!你這毒婦竟也來了?” 一聲冷哼從身側響起俐填,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤安接,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后英融,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盏檐,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年驶悟,在試婚紗的時候發(fā)現(xiàn)自己被綠了胡野。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡痕鳍,死狀恐怖硫豆,靈堂內的尸體忽然破棺而出龙巨,到底是詐尸還是另有隱情,我是刑警寧澤熊响,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布旨别,位于F島的核電站,受9級特大地震影響汗茄,放射性物質發(fā)生泄漏秸弛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一剔难、第九天 我趴在偏房一處隱蔽的房頂上張望胆屿。 院中可真熱鬧奥喻,春花似錦偶宫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冷离,卻和暖如春吵冒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背西剥。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工痹栖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞭空。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓揪阿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親咆畏。 傳聞我的和親對象是個殘疾皇子南捂,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容

  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調函...
    neromous閱讀 8,707評論 1 56
  • 本文適用的讀者 本文寫給有一定Promise使用經(jīng)驗的人旧找,如果你還沒有使用過Promise溺健,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,310評論 6 19
  • Promise 的含義 一句話概括一下promise的作用:可以將異步操作以同步操作的流程表達出來钮蛛,避免了層層嵌套...
    雪萌萌萌閱讀 5,489評論 0 7
  • 前言 本文旨在簡單講解一下javascript中的Promise對象的概念鞭缭,特性與簡單的使用方法。并在文末會附上一...
    _暮雨清秋_閱讀 2,200評論 0 3
  • Promiese 簡單說就是一個容器魏颓,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果缚去,語法上說,Pr...
    雨飛飛雨閱讀 3,358評論 0 19