10分鐘,讓你徹底明白Promise原理

2022-07-19 20:12:18 字數 3018 閱讀 5610

什麼是promise?本**用定外賣來舉例子,讓你明白。

// 定外賣就是乙個promise,promist的意思就是承諾

// 我們定完外賣,飯不會立即到我們手中

// 這時候我們和商家就要達成乙個承諾

// 在未來,不管飯是做好了還是燒糊了,都會給我們乙個答覆

function orderfood()else

}, 5000)})}

// 你在家上餓了麼定外賣

// 有一半的概率會把你的飯燒糊了

// 好在有承諾,他還是會告訴你

// 菜燒好執行,返回'我們的外賣正在給您派送了'

console.log('before order')

orderfood().then(res => console.log(res))

// 菜燒糊了執行,返回'不好意思,我們菜燒糊了,您再等一會'

.catch(res => console.log(res))

console.log('after order')

為了讓大家更容易理解,我們從乙個場景開始講解,讓大家一步一步跟著思路思考,相信你一定會更容易看懂。

考慮下面一種獲取使用者id的請求處理

//例1

function getuserid() )

})}getuserid().then(function(id) )

getuserid方法返回乙個promise,可以通過它的then方法註冊(注意註冊這個詞)在promise非同步操作成功時執行的**。這種執行方式,使得非同步呼叫變得十分順手。

那麼類似這種功能的promise怎麼實現呢?其實按照上面一句話,實現乙個最基礎的雛形還是很easy的。

function promise(fn) ;

function resolve(value) );

}fn(resolve);

}

上述**很簡單,大致的邏輯是這樣的:

呼叫then方法,將想要在promise非同步操作成功時執行的**放入callbacks佇列,其實也就是註冊**函式,可以向觀察者模式方向思考;

建立promise例項時傳入的函式會被賦予乙個函式型別的引數,即resolve,它接收乙個引數value,代表非同步操作返回的結果,當一步操作執行成功後,使用者會呼叫resolve方法,這時候其實真正執行的操作是將callbacks佇列中的**一一執行;

可以結合例1中的**來看,首先new promise時,傳給promise的函式傳送非同步請求,接著呼叫promise物件的then屬性,註冊請求成功的**函式,然後當非同步請求傳送成功時,呼叫resolve(results.id)方法, 該方法執行then方法註冊的**陣列。

相信仔細的人應該可以看出來,then方法應該能夠鏈式呼叫,但是上面的最基礎簡單的版本顯然無法支援鏈式呼叫。想讓then方法支援鏈式呼叫,其實也是很簡單的:

this.then = function (onfulfilled) ;

see?只要簡單一句話就可以實現類似下面的鏈式呼叫:

// 例2

getuserid().then(function (id) ).then(function (id) );

細心的同學應該發現,上述**可能還存在乙個問題:如果在then方法註冊**之前,resolve函式就執行了,怎麼辦?比如promise內部的函式是同步函式:

// 例3

function getuserid() );

}getuserid().then(function (id) );

這顯然是不允許的,promises/a+規範明確要求**需要通過非同步方式執行,用以保證一致可靠的執行順序。因此我們要加入一些處理,保證在resolve執行之前,then方法已經註冊完所有的**。我們可以這樣改造下resolve函式:

function resolve(value) );

}, 0)

}

上述**的思路也很簡單,就是通過settimeout機制,將resolve中執行**的邏輯放置到js任務佇列末尾,以保證在resolve執行時,then方法的**函式已經註冊完成.

剛開始看promise原始碼的時候總不能很好的理解then和resolve函式的執行機理,但是如果你靜下心來,反過來根據執行promise時的邏輯來推演,就不難理解了。這裡一定要注意的點是:promise裡面的then函式僅僅是註冊了後續需要執行的**,真正的執行是在resolve方法裡面執行的,理清了這層,再來分析原始碼會省力的多。

現在回顧下promise的實現過程,其主要使用了設計模式中的觀察者模式:

通過promise.prototype.then和promise.prototype.catch方法將觀察者方法註冊到被觀察者promise物件中,同時返回乙個新的promise物件,以便可以鏈式呼叫。

被觀察者管理內部pending、fulfilled和rejected的狀態轉變,同時通過建構函式中傳遞的resolve和reject方法以主動觸發狀態轉變和通知觀察者。

20分鐘徹底明白vue

初學vue時,使用script引入該框架,基本的語法過一遍,這不是什麼難事。進步到了這裡,通常不太明白的是vue的核心思想 資料驅動。一句話解釋 傳統jquery操作 html原始檔 瀏覽器解析 渲染為最終呈現頁面 vue資料繫結 html原始檔 vue攔截,進行dom diff計算 瀏覽器解析 渲...

10分鐘讓你的站點也支援Markdown

markdown 是一種輕量級的 標記語言 它的優點很多,目前也被越來越多的寫 好者,撰稿者廣泛使用。markdown 的語法十分簡單,常用的標記符號也不超過十個,這種相對於更為複雜的 html 標記語言來說,markdown 可謂是十分輕量的,學習成本也不需要太多,且一旦熟悉這種語法規則,會有一勞...

10分鐘放鬆你的肩

經常伏案工作,經常使用鍵盤 滑鼠的人群,總是會感覺自己的肩部沉重 痠疼。特別想找個人給揉揉,其實不用,只要每工作兩個小時,用10分鐘的時間做一些簡單的動作就可以緩解不適的感覺了。放鬆運動 1 坐姿伸展胸運動 坐於椅上,雙臂盡量向身體兩側伸展並做後拉動作,使胸部得到充分伸展,五指張開,雙腿向前自然彎曲...