卷兩根Weeds,搞懂Promise

前言

“盡管我已經(jīng)在使用promise來(lái)處理異步交互了,但是我面對(duì)各種resolve和reject、defer等字眼的時(shí)候還是一臉懵逼。我只知道then?!薄獖W利維亞威廉

Promise是一種設(shè)計(jì)模式

起初我總是被網(wǎng)上的傻逼欺騙,他們說(shuō):“所謂 Promise,就是一個(gè)對(duì)象,用來(lái)傳遞異步操作的消息。它代表了某個(gè)未來(lái)才會(huì)知道結(jié)果的事件(通常是一個(gè)異步操作),并且這個(gè)事件提供統(tǒng)一的 API,可供進(jìn)一步處理。”

這句話我聽不懂,但我不敢對(duì)別人說(shuō)我聽不懂,這樣顯得我是一個(gè)不合格的程序員,所以我在下面評(píng)論:“博主寫的不錯(cuò)。”
其實(shí)我在心里已經(jīng)把他從屁眼開始一路操到了天靈蓋?!峁爬?/p>

直到有一天,我遇到了Denny,一位混跡在鄉(xiāng)鎮(zhèn)夜市的程序員,他說(shuō):“promise就是一種設(shè)計(jì)模式,Q以及bluebird不就是根據(jù)這個(gè)設(shè)計(jì)模式寫出來(lái)的實(shí)現(xiàn)嗎?”
我聽后恍然大悟,Denny緩緩地拿起一顆毛豆,放到嘴里,“你要是足夠牛逼的話,你也可以照著這個(gè)設(shè)計(jì)模式寫一個(gè)自己的Promise。”
那一刻我感覺他是今晚的村鎮(zhèn)之王。

“用一種設(shè)計(jì)模式來(lái)解決異步的回調(diào)金字塔?!薄狣enny

Defer是什么

“已經(jīng)被淘汰了,別雞巴問了?!薄恢某绦騿T

我們用angular,我們用$q,我們四處都能看見Defer,我就是要問,這是一種信仰。接著,某個(gè)晚上我夢(mèng)到了一張圖,這個(gè)圖上畫著宇宙的真理。

image.png

promise是一個(gè)對(duì)象,有status屬性和value屬性,status屬性默認(rèn)是pendingvalue屬性默認(rèn)是undefined。
deferred是一個(gè)對(duì)象,同時(shí)promise是deferred的一個(gè)屬性,可以通過deferred.promise獲得:

var deferr  = Promise.defer();//這兒的Promise只是個(gè)恰巧重名的構(gòu)造函數(shù)
var promise = deferr.promise;
我一定要試試

“你是呆逼么?我告訴過你defer已經(jīng)被淘汰了” ——chrome61

resolve 和 reject

resolve和reject是defer對(duì)象的方法,用來(lái)操作自己的promise對(duì)象。

“我用resolve是為了操promise ”——不咬人的蚊子

  1. resolve方法接收一個(gè)參數(shù),可以將promise的status改為成功,并且將promise的value設(shè)置為傳進(jìn)去的參數(shù)。
  2. reject方法接收一個(gè)參數(shù),可以將promise的status改為失敗,并且將promise的value設(shè)置為傳進(jìn)去的參數(shù)。
defer和promise在視察工作

then vs catch

  1. catch方法用來(lái)注冊(cè)一個(gè)回調(diào)函數(shù),當(dāng)defer.reject被執(zhí)行的時(shí)候,這個(gè)回調(diào)函數(shù)就會(huì)被執(zhí)行。這個(gè)回調(diào)函數(shù)會(huì)拿取自己所在promise的value值作為參數(shù)
  2. then方法可以注冊(cè)兩個(gè)回調(diào)函數(shù)fn1和fn2,當(dāng)defer.resolve被執(zhí)行的時(shí)候,fn1執(zhí)行;當(dāng)defer.reject被執(zhí)行的時(shí)候,fn2執(zhí)行。這兩個(gè)個(gè)回調(diào)函數(shù)會(huì)拿取自己所在promise的value值作為參數(shù)。
catch(fn1);
then(fn1,fn2);

現(xiàn)在的Promise什么樣?

這樣:

var p = new Promise(function(resolve, reject){
});

“操你媽的resolve和reject到底是什么玩意兒?”——無(wú)名氏

當(dāng)Promise對(duì)象意識(shí)到自己的狀態(tài)不需要Defer這個(gè)對(duì)象來(lái)操作的時(shí)候,它就把Defer的這兩個(gè)方法搶了過來(lái)。一種更容易理解的方式是:resolve和reject是Promise在內(nèi)部定義的,操作自己status和value的方法,你可以假裝他們其實(shí)是通過兩個(gè)參數(shù)進(jìn)行了依賴注入,就像angular的$scope那樣

//angular的依賴注入
app.controller("userController", function ($scope) {
    $scope.name='userScope'//可以在這里操作scope
})
//Promise的構(gòu)造方法
var p = new Promise(function(resolve, reject){
  //用這個(gè)方法操作promise的狀態(tài)
  //當(dāng)構(gòu)造函數(shù)運(yùn)行的時(shí)候,下面的代碼會(huì)立刻執(zhí)行
   resolve("拿到的數(shù)據(jù)")
});

有圖為證:

image.png

“為什么當(dāng)我揍了Defer的臉并搶了他的錢包然后睡了他老婆以后,他就不愿意再理我了?難道我很過分嗎?”——知乎網(wǎng)友 Promise

.then()是啥原理

.then的原理要先明白.done的原理。

要想富,先脫褲,多生孩子少種樹?!固鼓崴雇品蛩够?/p>

那么.done()是啥原理

.done方法用于注冊(cè)兩個(gè)回調(diào)函數(shù)。在Promise內(nèi)部有一個(gè)回調(diào)函數(shù)倉(cāng)庫(kù),done方法用于向這個(gè)倉(cāng)庫(kù)里面放入兩個(gè)回調(diào)函數(shù)。
當(dāng)然,在放入倉(cāng)庫(kù)之前,done會(huì)看看當(dāng)前promise的狀態(tài),如果是已經(jīng)完成或者失敗的狀態(tài),那么done會(huì)直接執(zhí)行相應(yīng)回調(diào)函數(shù),就不往倉(cāng)庫(kù)里面推入了,畢竟倉(cāng)庫(kù)容量有限。
如果done在推入倉(cāng)庫(kù)之前發(fā)現(xiàn)當(dāng)前promise的狀態(tài)是執(zhí)行中,那么就直接推入倉(cāng)庫(kù),接下來(lái),當(dāng)resolve函數(shù)執(zhí)行的時(shí)候,resolve會(huì)檢查倉(cāng)庫(kù)里面的回調(diào)函數(shù)并且執(zhí)行他們。

“你的馬子我先幫你試試” ——Mr.done

運(yùn)行done時(shí),狀態(tài)還未知
運(yùn)行done時(shí),狀態(tài)已確定

現(xiàn)在可以說(shuō).then()的原理了

.then實(shí)際做的是:接受兩個(gè)回調(diào)函數(shù),利用done方法把兩個(gè)回調(diào)函數(shù)推入內(nèi)部倉(cāng)庫(kù),然后返回一個(gè)新的Promise對(duì)象,并且把自己的value值傳給新的Promise。于是就出現(xiàn)了then鏈。

promise.then().then().then();

“你快回家操自己吧?!?br> adj . Go Home And Fuck Yourself.
中國(guó)人喜歡用這句話形容一件事或者一個(gè)人很厲害。畢竟能像Promise那樣自己操自己是一件不容易的事。

例句:

  1. “我上個(gè)月漲工資了!”
    “你快回家操自己吧!”
  2. “你看到我剛才那個(gè)完美大了嗎?帥不帥氣!”
    “你快回家操自己吧。”
  3. “我覺得我這個(gè)想法能打敗馬化騰”
    “你快回家操自己吧?!?/li>

沒錯(cuò),寫這篇博客的時(shí)候我飛嗨了。如果本文對(duì)你有幫助,請(qǐng)給個(gè)贊好么,下一次我要一行一行寫一個(gè)自己的Promise。

“要個(gè)贊不過分吧,畢竟葉子都是我自己買的。” ——不咬人的蚊子

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容