有Promise,不會搞大肚子
Promise是專門給非同步計算用的物件,它表示一個現在還沒結果,但將來會給你算出來結果來的操作。
沒有大肚子的人生是更好的人生
權尾珍
憋說話,看圖....
圖片中的姑娘是韓國搞笑藝人權尾珍,其實她是一位諧星,體重曾經高達103公斤!後來參加了韓國一個減肥真人秀的節目,用三年時間減重51公斤。瘦下來後,權尾珍通過雜誌專欄、電臺、部落格向大眾分享了她的減肥經驗,“權式減肥法”也開始風靡韓國。
菲涅爾透鏡
你們小時候是不是都拿放大鏡照過螞蟻?!所以你們應該都知道什麼叫凸透鏡吧?菲涅爾透鏡也是一種凸透鏡,不過它和一般的凸透鏡不一樣。它不喜歡普通透鏡那種胖胖的身材,所以立志減肥,成功瘦身成了一枚纖細的透鏡。至於它為什麼叫菲涅爾透鏡,跟科學界的其他產物一樣,因為它是由法國物理學家奧古斯汀.菲涅爾(Augustin.Fresnel)發明的。那是在1822年,菲涅爾第一次把這種透鏡用在了燈塔上。哦,估計也只有用在燈塔上才能體現它身材上的優勢。
菲涅爾透鏡瘦身成功並不是靠慢跑,也不是靠舉鐵,更不是靠節食。它主要靠抽脂......科學總是有道理的,我們都知道,光的折射是發生在兩種介質相互接觸的表面的,(比如玻璃透鏡的表面),在一種介質內部是不會發生折射的,所以菲涅爾保留了透鏡表面的彎曲度,把裡面的東西掏空,把鼓鼓的透鏡壓扁,變成菲涅爾透鏡。理論上是像下面這樣:
按照這個理論做出來的菲涅爾透鏡是這樣的:
很瘦,但依然聚光。
有承諾,沒肚子
小姑娘要減肥大家已經司空見慣了。可是你看,連一塊透鏡都知道要瘦身,我們怎麼還好意思不鍛鍊呢?你可能會說我們碼農天天加班沒時間,那麼問題來了。既然你把時間都用在了程式碼上,怎麼還好意思讓自己的程式碼裡到處都是挺著大肚子的Callback呼叫鏈呢?不就是要按順序執行幾個非同步計算嗎?有必要非把自己程式碼的肚子搞大嗎?作為一名負責任的碼農,該採取措施還是要採取措施的,把Promise用起來,去掉Pyramid of Doom,還程式碼一個平坦的小腹,好不好?
Promise
Promise是專門給非同步計算用的物件,很早之前就作為神技在幾大門派間流傳,ES6之後被納入官庫。也就是說現在可以像下面這樣直接在程式碼中定義:
new Promise(function(resolve,reject) {
console.log("Start");
window.setTimeout(function() {
resolve();
}, 2000);
console.log("Waitting");
}).then(function() {
console.log("Finished!");
});
把上面的程式碼複製到Chrome開發者工具的控制檯中執行,得到的結果是這樣的:
上面的程式碼看起來還不太直觀,我們來分解一下:
/**
* 執行非同步操作的函式,2秒後呼叫
* 它的回撥函式resolve
*/
function asyncMission(resolve) {
window.setTimeout(function() {
resolve();
}, 2000);
}
/**
* 發起非同步操作的函式
* @param {function} resolve
* 非同步操作成功時呼叫的回撥函式
* @param {function} reject
* 非同步操作失敗時呼叫的回撥函式
*/
var executor = function(resolve,reject) {
console.log("Start");
asyncMission(resolve);
console.log("Waitting");
}
/**
* 建立一個Promise物件,引數為發起
* 非同步操作的那個函式executor
*/
var promiseMission = new Promise(executor);
/**
* 神祕的resolve終於現身了!
* 你可以把方法then的第一個引數
* 當作resolve
*/
promiseMission.then(function() {
console.log("Finished!");
});
看完上面這段程式碼,再來看看MDN上對Promise的定義:
The Promise object is used for asynchronous computations. A Promise represents an operation that hasn't completed yet, but is expected in the future.
看不懂英文沒關係,這不正好我在嘛!給你翻譯一下,用中國話說,定義一個Promise
就相當於老大跟你說:“你出趟遠門,老子有個非同步計算的差事要交給你辦,事成之後,____________"。看到沒,給了張空白支票!!!而then
就是讓你填那個空的方法,事成之後你想幹什麼,告訴then
就成了。
不過你應該知道的,老大都是很有原則的人,不會像我上面寫的程式碼一樣,只告訴你事成之後可以怎麼樣。說完好處,他的臉上一定還會浮現出諱莫如深的、蛋蛋的憂傷,告訴你辦不成應該怎樣。所以一個完整的Promise
應該是這樣的:
var p1 = new Promise(
function(resolve, reject) {
window.setTimeout(
function() {
resolve(Math.random());
}, 2000);
}
);
p1.then(
// resolve,val就是上面那個Math.random()的值
function(val) {
console.log(val);
})
.catch(
// reject
function(reason) {
console.log('搞砸了,',reason);
});
Promise一直都知道,在經過漫長的pending之後,事情總會有settled的時候。但settled的結果,有可能是fulfilled,也有可能是rejected。所以我們可以用then
告訴它事成之後怎麼辦,也可以用catch
告訴它失敗了怎麼辦。關於Promise
,我要說的這麼多;不過關於then
,還有很多話要說。
then(what)?
then
是減掉大肚子的關鍵,看清了then是什麼,就算是掌握了Promise的奧義。來,請看MDN中對then的定義:
The then() method returns a Promise. It takes two arguments: callback functions for the success and failure cases of the Promise.
所有的祕密都在第一句話裡......
在前面所有的程式碼裡,都隱藏著一個很容易被忽視的事實,then
也是有返回值的,而且它返回的就是Promise
!不要忘了,我們看到的那個函式只是它的引數,不管它的引數有沒有返回值,then
都會返回一個Promise。我們可以簡單地把then的實現理解成下面這個樣子:
then(resolve,reject) {
var val = resolve();
return new Promise(
function(_resolve,_reject) {
_resolve(val)
});
}
所以整個故事大概是這樣的:開始建立Promise的時候,我們只知道它的引數是一個函式,而這個函式的引數是兩個回撥函式。這兩個回撥函式一個是在Promise被fulfilled時呼叫的resolve,一個是Promise被rejected時呼叫的reject;但這兩個回撥函式具體長什麼我們並不知道。然後then
登場了,它的引數就是那個神祕的resolve回撥函式。哦,對,then
也可以用第二個引數指出reject是誰,但那是2B碼農的寫法,優雅的程式猿輕易不會露出那麼急赤白臉的吃相,reject應該作為catch
的引數出現。
既然then
返回的是Promise
,那then
(和catch
)之後就可以接著then
(和catch
),然後再then
(和catch
),這樣callback的呼叫就可以從回撥函式裡提出來,放到then
中去,回撥函式的呼叫鏈就變成平坦的了。
當然,我們都知道,健身不光能讓體型好看,還有很多額外的好處,比如血壓血脂膽固醇什麼的。用Promise寫程式碼也有很多額外的好處,我就不說了,留著你自己慢慢體會吧。
最後,為了感謝你有看這麼長時間的耐心,整點乾貨。
PyramidOfDoom VS chainedThen
憋說話,看程式碼:
function mission(duration,callback) {
console.log(`Mission ${duration/1000} Start at ${Date.now()}`);
window.setTimeout(function() {
console.log(`Waitting Mission ${duration/1000}`);
callback(duration);
}, duration);
}
(function pyramidOfDoom() {
mission(1000,function() {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
mission(2000,function() {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
mission(3000,function() {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
mission(4000,function() {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
mission(5000,function() {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
mission(6000,function() {
console.log("All missions Completed!");
})
})
})
})
})
});
})();
再看這個:
function promiseMission(duration) {
console.log(`Mission ${duration/1000} Start at ${Date.now()}`);
return new Promise(function(resolve,reject) {
window.setTimeout(function() {
resolve(duration);
console.log(`Waitting Mission ${duration/1000}`);
}, duration);
});
}
promiseMission(1000)
.then(function(duration) {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
return missionPromise(duration+1000);
})
.then(function(duration) {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
return missionPromise(duration+1000);
})
.then(function(duration) {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
return missionPromise(duration+1000);
})
.then(function(duration) {
console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);
return missionPromise(duration+1000);
})
.then(function() {
console.log("All missions Completed!");
})
最後再安利一個教程,優達學院有個免費的JavaScript Promise課程可以看看。
還有我的公眾號,也可以關注一下:
相關文章
- Promise不會??看這裡!!!史上最通俗易懂的Promise!!!Promise
- Promise 不夠中立Promise
- 不會吧不會吧,還有開發不會Java填充PDF模板資料的,趕緊看看吧Java
- 惡搞谷歌翻譯,傷不起!谷歌
- 互動解謎遊戲書有搞頭嗎?暫時不推薦入坑遊戲
- ora-15064會不會跟沒有安裝asmlib有關?ASM
- 英偉達 GTC 大會不僅有 AI 晶片,還有 AI for ScienceAI晶片
- 從設計模式角度分析Promise:手撕Promise並不難設計模式Promise
- iPhone SE不會有第二代?iPhone
- 為什麼Facebook不會有“dislike”按鈕?
- 有了 GC 還會不會發生記憶體洩漏?GC記憶體
- 有頭有臉的大資料風控服務商,終究逃不過搞貸款這條路大資料
- [一道題搞蒙你] - setTimeout 與 Promise 執行順序Promise
- 有了垃圾回收,還會不會發生記憶體洩漏?記憶體
- 想搞ios不會這個怎麼行,為你推薦一份swift書單!iOSSwift
- 搞程式有風險 修bug需謹慎
- Spring IOC 特性有哪些,不會讀不懂原始碼!Spring原始碼
- 再談Promise以及其實現-沒有基於Promise/A規範Promise
- javascript中promise有什麼侷限JavaScriptPromise
- Promise、Generator、Async有什麼區別?Promise
- SQL 最佳化極簡法則,還有誰不會?SQL
- 搞基礎理論研究有什麼用?
- 【學習筆記】不會吧不會吧,不會有人還在手寫堆吧筆記
- 【前端】一文徹底學會Promise前端Promise
- Promise 必知必會(十道題)Promise
- 不會git的程式設計師,會不會被鄙視?Git程式設計師
- 實用的幾種電腦技巧,有哪些你還不會?
- 深度模型的日誌異常檢測,還有誰不會?模型
- 不會PS技術做電商有什麼快速作圖工具?
- 如果沒有Java 人類就像不會說話的嬰兒Java
- 賣實名認證介面有沒有搞頭?
- 遊戲開發中的“門”,有多難搞?遊戲開發
- 融雲猿桌派:聽說女生不適合搞 IT,哈?
- 答 “SOA會不會造成IT黑洞?”
- 什麼是 Promise.allSettled() !新手老手都要會?Promise
- 【轉】Promise 必知必會(十道題)Promise
- 還有程式設計師不會玩黑神話悟空?是我太菜了程式設計師
- 遊戲植入廣告 這種盈利模式有搞頭嗎?遊戲模式