一道Promise經典問題

本文章多處借鑒了百度FEX上的一篇譯文,地址:[翻譯] We have a problem with promises

感謝百度FEX為前端開發者提供了這篇優秀的譯文。

也感謝Nolan Lawson

先看一下問題原文,這是Nolan Lawson在Twitter上發布一篇推文。原文地址(Twitter):twitter.com/nolanlawson

大概意思就是說,如果你能說出這四個語句的不同就是一個Promise大拿了,但估計應該大部分JS開發者都答不出來。


知識回顧

Promise.then()方法接受兩個參數,這兩個參數的類型必須是函數,在第一個參數函數內,你只可以做下面三件事:

  1. return另一個Promise
  2. return一個同步值(包括undefined)
  3. 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

TAG:前端开发 | Promise | 异步 |