什麼是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 坐姿伸展胸運動 坐於椅上,雙臂盡量向身體兩側伸展並做後拉動作,使胸部得到充分伸展,五指張開,雙腿向前自然彎曲...