一道Promise經典問題
本文章多處借鑒了百度FEX上的一篇譯文,地址:[翻譯] We have a problem with promises
感謝百度FEX為前端開發者提供了這篇優秀的譯文。也感謝Nolan Lawson
先看一下問題原文,這是Nolan Lawson在Twitter上發布一篇推文。原文地址(Twitter):https://twitter.com/nolanlawson/status/578948854411878400
大概意思就是說,如果你能說出這四個語句的不同就是一個Promise大拿了,但估計應該大部分JS開發者都答不出來。
知識回顧
Promise.then()方法接受兩個參數,這兩個參數的類型必須是函數,在第一個參數函數內,你只可以做下面三件事:
- return另一個Promise
- return一個同步值(包括undefined)
- throw一個異常
回顧上面這個重要的知識點,會有助於你理解上面題目的運行機制。
揭曉答案
問題#1
解析:這是一個很正常的語法,無需過多解釋
doSomething().then(function () {n return doSomethingElse();n}).then(finalHandler);n
運行結果
doSomethingn|-----------------|n doSomethingElse(undefined)n |------------------|n finalHandler(resultOfDoSomethingElse)n |------------------|n
問題#2
解析:
這裡和第一問相比,缺少了重要的返回值,那麼JS會默認返回undefined。而如果返回undefined這個同步值的話,這個then所代表的Promise會立即決議為undefined,並開始下一個then的運行。
所以這兩個then幾乎是同時運行的。
doSomething().then(function () {n doSomethingElse();n}).then(finalHandler);n
運行結果:
doSomethingn|-----------------|n doSomethingElse(undefined)n |------------------|n finalHandler(undefined)n |------------------|n
問題#3
解析: 這道題確實有些意外,then只接受function類型的參數,而此處傳入的並非function類型,所以為會認為傳入了一個null,其結果和.then(null)是一樣的。這樣會導致前一個promise會穿透到下面。
doSomething().then(doSomethingElse())n .then(finalHandler);n
運行結果:
doSomethingn|-----------------|ndoSomethingElse(undefined)n|---------------------------------|n finalHandler(resultOfDoSomething)n |------------------|n
問題#4
解析:這道題其實和第一個是相同的,運行順序自然也是一致的,所以也無需過多解釋了。
doSomething().then(doSomethingElse)n .then(finalHandler);n
運行結果:
doSomethingn|-----------------|n doSomethingElse(resultOfDoSomething)n |------------------|n finalHandler(resultOfDoSomethingElse)n |------------------|n
總結
Promise其實不止於一個非同步的解決方案,而更是一種代碼結構和流程。如果將Promise運用的好會寫出非常優雅的代碼和清晰的結構。
推薦閱讀:
※SF 講堂推薦「Promise 的 N 種用法」要開播啦
※Promise.then(fill) 中如何在 fill 的非同步邏輯中改變PromiseStatus?
※async/await使用rabbitMQ