日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一文帶你使用Swift實(shí)現(xiàn)Promise

前言

我最近在找如何使用 Swift 實(shí)現(xiàn) Promise 的資料,因?yàn)闆]找到好的文章,所以我想自己寫一篇。通過本文,我們將實(shí)現(xiàn)自己的 Promise 類型,以便明了其背后的邏輯。

成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的斗門網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

要注意這個(gè)實(shí)現(xiàn)完全不適合生產(chǎn)環(huán)境。例如,我們的 Promise 沒有提供任何錯(cuò)誤機(jī)制,也沒有覆蓋線程相關(guān)的場(chǎng)景。我會(huì)在文章的后面提供一些有用的資源以及完整實(shí)現(xiàn)的鏈接,以饗愿深入挖掘的讀者。

注:為了讓本教程更有趣一點(diǎn),我選擇使用 TDD 來進(jìn)行介紹。我們會(huì)先寫測(cè)試,然后確保它們一個(gè)個(gè)通過。

第一個(gè)測(cè)試

先寫第一個(gè)測(cè)試:

 
 
 
 
  1. test(named: "0. Executor function is called immediately") { assert, done in
  2.     var string: String = ""
  3.     _ = Promise { string = "foo" }
  4.     assert(string == "foo")
  5.     done()
  6. }

通過此測(cè)試,我們想實(shí)現(xiàn):傳遞一個(gè)函數(shù)給 Promise 的初始化函數(shù),并立即調(diào)用此函數(shù)。

注:我們沒有使用任何測(cè)試框架,僅僅使用一個(gè)自定義的test方法,它在 Playground 中模擬斷言(gist[1])。

當(dāng)我們運(yùn)行 Playground,編譯器會(huì)報(bào)錯(cuò):

 
 
 
 
  1. error: Promise.playground:41:9: error: use of unresolved identifier 'Promise'
  2.     _ = Promise { string = "foo" }
  3.         ^~~~~~~

合理,我們需要定義 Promise 類。

 
 
 
 
  1. class Promise {
  2. }

再運(yùn)行,錯(cuò)誤變?yōu)椋?/p>

 
 
 
 
  1. error: Promise.playground:44:17: error: argument passed to call that takes no arguments
  2.     _ = Promise { string = "foo" }
  3.                 ^~~~~~~~~~~~~~~~~~

我們必須定義一個(gè)初始化函數(shù),它接受一個(gè)閉包作為參數(shù)。而且這個(gè)閉包應(yīng)該被立即調(diào)用。

 
 
 
 
  1. class Promise {
  2.     init(executor: () -> Void) {
  3.         executor()
  4.     }
  5. }

由此,我們通過第一個(gè)測(cè)試。目前我們還沒有寫出什么值得夸耀的東西,但耐心一點(diǎn),我們的實(shí)現(xiàn)將在下一節(jié)繼續(xù)增長(zhǎng)。

 
 
 
 
  1. ? Test 0. Executor function is called immediately passed 

我們先將此測(cè)試注釋掉,因?yàn)閷淼?Promise 實(shí)現(xiàn)會(huì)變得有些不同。

最低限度

第二個(gè)測(cè)試如下:

 
 
 
 
  1. test(named: "1.1 Resolution handler is called when promise is resolved sync") { assert, done in
  2.     let string: String = "foo"
  3.     let promise = Promise { resolve in
  4.         resolve(string)
  5.     }
  6.     promise.then { (value: String) in
  7.         assert(string == value)
  8.         done()
  9.     }
  10. }

這個(gè)測(cè)試挺簡(jiǎn)單,但我們添加了一些新內(nèi)容到 Promise 類。我們創(chuàng)建的這個(gè) promise 有一個(gè) resolution handler(即閉包的resolve參數(shù)),之后立即調(diào)用它(傳遞一個(gè) value)。然后,我們使用 promise 的 then 方法來訪問 value 并用斷言確保其值。

在開始實(shí)現(xiàn)之前,我們需要引入另外一個(gè)不太一樣的測(cè)試。

 
 
 
 
  1. test(named: "1.2 Resolution handler is called when promise is resolved async") { assert, done in
  2.     let string: String = "foo"
  3.     let promise = Promise { resolve in
  4.         after(0.1) {
  5.             resolve(string)
  6.         }
  7.     }
  8.     promise.then { (value: String) in
  9.         assert(string == value)
  10.         done()
  11.     }
  12. }

不同于測(cè)試 1.1,這里的resove方法被延遲調(diào)用。這意味著,在then里,value 不會(huì)立馬可用(因?yàn)?0.1 秒的延遲,調(diào)用then時(shí),resolve還未被調(diào)用)。

我們開始理解這里的“問題”。我們必須處理異步。

我們的 promise 是一個(gè)狀態(tài)機(jī)。當(dāng)它被創(chuàng)建時(shí),promise 處于pending狀態(tài)。一旦resolve方法被調(diào)用(與一個(gè) value),我們的 promise 將轉(zhuǎn)到resolved狀態(tài),并存儲(chǔ)這個(gè) value。

then方法可在任意時(shí)刻被調(diào)用,而不管 promise 的內(nèi)部狀態(tài)(即不管 promise 是否已有一個(gè) value)。當(dāng)這個(gè) promise 處于pending狀態(tài)時(shí),我們調(diào)用then,value 將不可用,因此,我們需要存儲(chǔ)此回調(diào)。之后一旦 promise 變成resolved,我們就能使用 resolved value 來觸發(fā)同樣的回調(diào)。

現(xiàn)在我們對(duì)要實(shí)現(xiàn)的東西有了更好的理解,那就先以修復(fù)編譯器的報(bào)錯(cuò)開始。

 
 
 
 
  1. error: Promise.playground:54:19: error: cannot specialize non-generic type 'Promise'
  2.     let promise = Promise { resolve in
  3.                   ^      ~~~~~~~~

我們必須給Promise類型添加泛型。誠(chéng)然,一個(gè) promise 是這樣的東西:它關(guān)聯(lián)著一個(gè)預(yù)定義的類型,并能在被解決時(shí),將一個(gè)此類型的 value 保留住。

 
 
 
 
  1. class Promise {
  2.     init(executor: () -> Void) {
  3.         executor()
  4.     }
  5. }

現(xiàn)在錯(cuò)誤為:

 
 
 
 
  1. error: Promise.playground:54:37: error: contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body
  2.     let promise = Promise { resolve in
  3.                                     ^

我們必須提供一個(gè)resolve函數(shù)傳遞給初始化函數(shù)(即 executor)。

 
 
 
 
  1. class Promise {
  2.     init(executor: (_ resolve: (Value) -> Void) -> Void) {
  3.         executor()
  4.     }
  5. }

注意這個(gè) resolve 參數(shù)是一個(gè)函數(shù),它消耗一個(gè) value:(Value) -> Void。一旦 value 被確定,這個(gè)函數(shù)將被外部世界調(diào)用。

編譯器依然不開心,因?yàn)槲覀冃枰峁┮粋€(gè)resolve函數(shù)給executor。讓我們創(chuàng)建一個(gè)private的吧。

 
 
 
 
  1. class Promise {
  2.     init(executor: (_ resolve: @escaping (Value) -> Void) -> Void) {
  3.         executor(resolve)
  4.     }
  5.     private func resolve(_ value: Value) -> Void {
  6.         // To implement
  7.         // This will be called by the outside world when a value is determined
  8.     }
  9. }

我們將在稍后實(shí)現(xiàn)resolve,當(dāng)所有錯(cuò)誤都被解決時(shí)。

下一個(gè)錯(cuò)誤很簡(jiǎn)單,方法then還未定義。

 
 
 
 
  1. error: Promise.playground:61:5: error: value of type 'Promise' has no member 'then'
  2.     promise.then { (value: String) in
  3.     ^~~~~~~ ~~~~

讓我們修復(fù)之。

 
 
 
 
  1. class Promise {
  2.     init(executor: (_ resolve: @escaping (Value) -> Void) -> Void) {
  3.         executor(resolve)
  4.     }
  5.     func then(onResolved: @escaping (Value) -> Void) {
  6.         // To implement
  7.     }
  8.     private func resolve(_ value: Value) -> Void {
  9.         // To implement
  10.     }
  11. }

現(xiàn)在編譯器開心了,讓我們回到開始的地方。

我們之前說過一個(gè)Promise就是一個(gè)狀態(tài)機(jī),它有一個(gè)pending狀態(tài)和一個(gè)resolved狀態(tài)。我們可以使用 enum 來定義它們。

 
 
 
 
  1. enum State {
  2.     case pending
  3.     case resolved(T)
  4. }

Swift 的美妙讓我們可以直接存儲(chǔ) promise 的 value 在 enum 中。

現(xiàn)在我們需要在Promise的實(shí)現(xiàn)中定義一個(gè)狀態(tài),其默認(rèn)值為.pending。我們還需要一個(gè)私有函數(shù),它能在當(dāng)前還處于.pending狀態(tài)時(shí)更新狀態(tài)。

 
 
 
 
  1. class Promise {
  2.     enum State {
  3.         case pending
  4.         case resolved(T)
  5.     }
  6.     private var state: State = .pending
  7.     init(executor: (_ resolve: @escaping (Value) -> Void) -> Void) {
  8.         executor(resolve)
  9.     }
  10.     func then(onResolved: @escaping (Value) -> Void) {
  11.         // To implement
  12.     }
  13.     private func resolve(_ value: Value) -> Void {
  14.         // To implement
  15.     }
  16.     private func updateState(to newState: State) {
  17.         guard case .pending = state else { return }
  18.         state = newState
  19.     }
  20. }

注意updateState(to:)函數(shù)先檢查了當(dāng)前處于.pending狀態(tài)。如果 promise 已經(jīng)處于.resolved狀態(tài),那它就不能再變成其他狀態(tài)了。

現(xiàn)在是時(shí)候在必要時(shí)更新 promise 的狀態(tài),即,當(dāng)resolve函數(shù)被外部世界傳遞 value 調(diào)用時(shí)。

 
 
 
 
  1. private func resolve(_ value: Value) -> Void {
  2.     updateState(to: .resolved(value))
  3. }

快好了,只缺少 then 方法還未實(shí)現(xiàn)。我們說過必須存儲(chǔ)回調(diào),并在 promise 被解決時(shí)調(diào)用回調(diào)。這就來實(shí)現(xiàn)之。

 
 
 
 
  1. class Promise {
  2.     enum State {
  3.         case pending
  4.         case resolved(T)
  5.     }
  6.     private var state: State = .pending
  7.     // we store the callback as an instance variable
  8.     private var callback: ((Value) -> Void)?
  9.     init(executor: (_ resolve: @escaping (Value) -> Void) -> Void) {
  10.         executor(resolve)
  11.     }
  12.     func then(onResolved: @escaping (Value) -> Void) {
  13.         // store the callback in all cases
  14.         callback = onResolved
  15.         // and trigger it if needed
  16.         triggerCallbackIfResolved()
  17.     }
  18.     private func resolve(_ value: Value) -> Void {
  19.         updateState(to: .resolved(value))
  20.     }
  21.     private func updateState(to newState: State) {
  22.         guard case .pending = state else { return }
  23.         state = newState
  24.         triggerCallbackIfResolved()
  25.     }
  26.     private func triggerCallbackIfResolved() {
  27.         // the callback can be triggered only if we have a value,
  28.         // meaning the promise is resolved
  29.         guard case let .resolved(value) = state else { return }
  30.         callback?(value)
  31.         callback = nil
  32.     }
  33. }

我們定義了一個(gè)實(shí)例變量callback,以在 promise 處于.pending狀態(tài)時(shí)保留回調(diào)。同時(shí)我們創(chuàng)建一個(gè)方法triggerCallbackIfResolved,它先檢查狀態(tài)是否為.resolved,然后傳遞拆包的 value 給回調(diào)。這個(gè)方法在兩個(gè)地方被調(diào)用。一個(gè)是then方法中,如果 promise 已經(jīng)在調(diào)用then時(shí)被解決。另一個(gè)在updateState方法中,因?yàn)槟鞘?promise 更新其內(nèi)部狀態(tài)從.pending到.resolved的地方。

有了這些修改,我們的測(cè)試就成功通過了。

 
 
 
 
  1. ? Test 1.1 Resolution handler is called when promise is resolved sync passed (1 assertions)
  2. ? Test 1.2 Resolution handler is called when promise is resolved async passed (1 assertions)

我們走對(duì)了路,但我們還需要做出一點(diǎn)改變,以得到一個(gè)真正的Promise實(shí)現(xiàn)。先來看看測(cè)試。

 
 
 
 
  1. test(named: "2.1 Promise supports many resolution handlers sync") { assert, done in
  2.     let string: String = "foo"
  3.     let promise = Promise { resolve in
  4.         resolve(string)
  5.     }
  6.     promise.then { value in
  7.         assert(string == value)
  8.     }
  9.     promise.then { value in
  10.         assert(string == value)
  11.         done()
  12.     }
  13. }
 
 
 
 
  1. test(named: "2.2 Promise supports many resolution handlers async") { assert, done in
  2.     let string: String = "foo"
  3.     let promise = Promise { resolve in
  4.         after(0.1) {
  5.             resolve(string)
  6.         }
  7.     }
  8.     promise.then { value in
  9.         assert(string == value)
  10.     }
  11.     promise.then { value in
  12.         assert(string == value)
  13.         done()
  14.     }
  15. }

這回我們對(duì)每個(gè) promise 都調(diào)用了兩次then。

先看看測(cè)試輸出。

 
 
 
 
  1. ? Test 2.1 Promise supports many resolution handlers sync passed (2 assertions)
  2. ? Test 2.2 Promise supports many resolution handlers async passed (1 assertions)

雖然測(cè)試通過了,但你可能也注意問題。測(cè)試 2.2 只有一個(gè)斷言,但應(yīng)該是兩個(gè)。

如果我們思考一下,這其實(shí)符合邏輯。誠(chéng)然,在異步的測(cè)試 2.2 中,當(dāng)?shù)谝粋€(gè)then被調(diào)用時(shí),promise 還處于.pending狀態(tài)。如我們之前所見,我們存儲(chǔ)了第一次then的回調(diào)。但當(dāng)我們第二次調(diào)用then時(shí),promise 還是沒有被解決,依然處于.pending狀態(tài),于是,我們將回調(diào)擦除換成了新的。只有第二個(gè)回調(diào)會(huì)在將來被執(zhí)行,第一個(gè)被忘記了。這使得測(cè)試雖然通過,但只有一個(gè)斷言而不是兩個(gè)。

解決辦法也很簡(jiǎn)單,就是存儲(chǔ)一個(gè)回調(diào)的數(shù)組,并在promise被解決時(shí)觸發(fā)它們。

讓我們更新一下。

 
 
 
 
  1. class Promise {
  2.     enum State {
  3.         case pending
  4.         case resolved(T)
  5.     }
  6.     private var state: State = .pending
  7.     // We now store an array instead of a single function
  8.     private var callbacks: [(Value) -> Void] = []
  9.     init(executor: (_ resolve: @escaping (Value) -> Void) -> Void) {
  10.         executor(resolve)
  11.     }
  12.     func then(onResolved: @escaping (Value) -> Void) {
  13.         callbacks.append(onResolved)
  14.         triggerCallbacksIfResolved()
  15.     }
  16.     private func resolve(_ value: Value) -> Void {
  17.         updateState(to: .resolved(value))
  18.     }
  19.     private func updateState(to newState: State) {
  20.         guard case .pending = state else { return }
  21.         state = newState
  22.         triggerCallbacksIfResolved()
  23.     }
  24.     private func triggerCallbacksIfResolved() {
  25.         guard case let .resolved(value) = state else { return }
  26.         // We trigger all the callbacks
  27.         callbacks.forEach { callback in callback(value) }
  28.         callbacks.removeAll()
  29.     }
  30. }

測(cè)試通過,而且都有兩個(gè)斷言。

 
 
 
 
  1. ? Test 2.1 Promise supports many resolution handlers sync passed (2 assertions)
  2. ? Test 2.2 Promise supports many resolution handlers async passed (2 assertions)

恭喜!我們已經(jīng)創(chuàng)建了自己的Promise類。你已經(jīng)可以使用它來抽象異步邏輯,但它還有限制。

注:如果從全局來看,我們知道then可以被重命名為observe。它的目的是消費(fèi) promise 被解決后的 value,但它不返回什么。這意味著我們暫時(shí)沒法串聯(lián)多個(gè) promise。

串聯(lián)多個(gè) Promise

如果我們不能串聯(lián)多個(gè) promise,那我們的Promise實(shí)現(xiàn)就不算完整。

先來看看測(cè)試,它將幫助我們實(shí)現(xiàn)這個(gè)特性。

 
 
 
 
  1. test(named: "3. Resolution handlers can be chained") { assert, done in
  2.     let string: String = "foo"
  3.     let promise = Promise { resolve in
  4.         after(0.1) {
  5.             resolve(string)
  6.         }
  7.     }
  8.     promise
  9.         .then { value in
  10.             return Promise { resolve in
  11.                 after(0.1) {
  12.                     resolve(value + value)
  13.                 }
  14.             }
  15.         }
  16.         .then { value in // the "observe" previously defined
  17.             assert(string + string == value)
  18.             done()
  19.         }
  20. }

如測(cè)試所見,第一個(gè)then創(chuàng)建了一個(gè)有新 value 的新Promise并返回了它。第二個(gè)then(我們前一節(jié)定義的,被稱為observe)被串聯(lián)在后面,它訪問新的 value(其將是"foofoo")。

我們很快在終端里看到錯(cuò)誤。

 
 
 
 
  1. error: Promise.playground:143:10: error: value of tuple type '()' has no member 'then'
  2.         .then { value in
  3.          ^

我們必須創(chuàng)建一個(gè)then的重載,它接受一個(gè)能返回 promise 的函數(shù)。為了能夠串聯(lián)調(diào)用then,這個(gè)方法必須也返回一個(gè)promise。這個(gè)then的原型如下。

 
 
 
 
  1. func then(onResolved: @escaping (Value) -> Promise) -> Promise {
  2.     // to implement
  3. }

注:細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn),我們?cè)诮oPromise實(shí)現(xiàn)flatMap。就如給Optional和Array定義flatMap一樣,我們也可以給Promise定義它。

困難來了。讓我們一步步看看這個(gè)“flatMap”的then要怎么實(shí)現(xiàn)。

  • 我們需要返回一個(gè)Promise
  • 誰給我們這樣一個(gè) promise?onResolved 方法
  • 但onResolved 需要一個(gè)類型為Value的 value 為參數(shù)。我們?cè)撛鯓拥玫竭@個(gè) value? 我們可以使用之前定義的then(或者說 “observe”) 來在其可用時(shí)訪問它

如果寫成代碼,大概如下:

 
 
 
 
  1. func then(onResolved: @escaping (Value) -> Promise) -> Promise {
  2.     then { value in // the "observe" one
  3.         let promise = onResolved(value) // `promise` is a Promise
  4.         // problem: how do we return `promise` to the outside ??
  5.     }
  6.     return // ??!!
  7. }

就快好了。但我們還有個(gè)小問題需要修復(fù):這個(gè)promise變量被傳遞給then的閉包所限制。我們不能將其作為函數(shù)的返回值。

我們要使用的技巧是創(chuàng)建一個(gè)包裝Promise ,它將執(zhí)行我們目前所寫的代碼,然后在promise變量解決時(shí)被同時(shí)解決。換句話說,當(dāng)onResolved方法提供的 promise 被解決并從外部得到一個(gè)值,那包裝的 promise 也就被解決并得到同樣的值。

可能文字有些抽象,但如果我們寫成代碼,將看得更清楚:

 
 
 
 
  1. func then(onResolved: @escaping (Value) -> Promise) -> Promise {
  2.     // We have to return a promise, so let's return a new one
  3.     return Promise { resolve in
  4.         // this is called immediately as seen in test 0.
  5.         then { value in // the "observe" one
  6.             let promise = onResolved(value) // `promise` is a Promise
  7.             // `promise` has the same type of the Promise wrapper
  8.             // we can make the wrapper resolves when the `promise` resolves
  9.             // and gets a value
  10.             promise.then { value in resolve(value) }
  11.         }
  12.     }
  13. }

如果我們整理一下代碼,我們將有這樣兩個(gè)方法:

 
 
 
 
  1. // observe
  2. func then(onResolved: @escaping (Value) -> Void) {
  3.     callbacks.append(onResolved)
  4.     triggerCallbacksIfResolved()
  5. }
  6. // flatMap
  7. func then(onResolved: @escaping (Value) -> Promise) -> Promise {
  8.     return Promise { resolve in
  9.         then { value in
  10.             onResolved(value).then(onResolved: resolve)
  11.         }
  12.     }
  13. }

最后,測(cè)試通過。

 
 
 
 
  1. ? Test 3. Resolution handlers can be chained passed (1 assertions)

串聯(lián)多個(gè) value

如果你能給某個(gè)類型實(shí)現(xiàn)flatMap,那你就能利用flatMap為其實(shí)現(xiàn)map。對(duì)于我們的Promise來說,map該是什么樣子?

我們將使用如下測(cè)試:

 
 
 
 
  1. test(named: "4. Chaining works with non promise return values") { assert, done in
  2.     let string: String = "foo"
  3.     let promise = Promise { resolve in
  4.         after(0.1) {
  5.             resolve(string)
  6.         }
  7.     }
  8.     promise
  9.         .then { value -> String in
  10.             return value + value
  11.         }
  12.         .then { value in // the "observe" then
  13.             assert(string + string == value)
  14.             done()
  15.         }
  16. }

注意第一個(gè)then沒有再返回一個(gè)Promise,而是將其接收的值做了一個(gè)變換。這個(gè)新的then就對(duì)應(yīng)于我們想添加的map。

編譯器報(bào)錯(cuò)說我們必須實(shí)現(xiàn)此方法。

 
 
 
 
  1. error: Promise.playground:174:26: error: declared closure result 'String' is incompatible with contextual type 'Void'
  2.         .then { value -> String in
  3.                          ^~~~~~
  4.                          Void

這個(gè)方法很接近flatMap,唯一的不同是其參數(shù)onResolved函數(shù)返回一個(gè)NewValue而不是Promise 。

 
 
 
 
  1. // map
  2. func then(onResolved: @escaping (Value) -> NewValue) -> Promise {
  3.     // to implement
  4. }

之前我們說可以利用flatMap實(shí)現(xiàn)map。在我們的情況里,我們看到我們需要返回一個(gè)Promise 。如果我們使用這個(gè)“flatMap”的then,并創(chuàng)建一個(gè)promise,再以映射后的 value 來直接解決,我們就搞定了。讓我來證明之。

 
 
 
 
  1. // map
  2. func then(onResolved: @escaping (Value) -> NewValue) -> Promise {
  3.     return then { value in // the "flatMap" defined before
  4.         // must return a Promise here
  5.         // this promise directly resolves with the mapped value
  6.         return Promise { resolve in
  7.             let newValue = onResolved(value)
  8.             resolve(newValue)
  9.         }
  10.     }
  11. }

再一次,測(cè)試通過。

 
 
 
 
  1. ? Test 4. Chaining works with non promise return values passed (1 assertions)

如果我們移除注釋,再看看我們做出了什么。我們有三個(gè)then方法的實(shí)現(xiàn),能被使用或串聯(lián)。

 
 
 
 
  1. // observe
  2. func then(onResolved: @escaping (Value) -> Void) {
  3.     callbacks.append(onResolved)
  4.     triggerCallbacksIfResolved()
  5. }
  6. // flatMap
  7. func then(onResolved: @escaping (Value) -> Promise) -> Promise {
  8.     return Promise { resolve in
  9.         then { value in
  10.             onResolved(value).then(onResolved: resolve)
  11.         }
  12.     }
  13. }
  14. // map
  15. func then(onResolved: @escaping (Value) -> NewValue) -> Promise {
  16.     return then { value in
  17.         return Promise { resolve in
  18.             resolve(onResolved(value))
  19.         }
  20.     }
  21. }

使用示例

實(shí)現(xiàn)告一段落。我們的Promise類已足夠完整來展示我們能夠用它做什么。

假設(shè)我們的app有一些用戶,結(jié)構(gòu)如下:

 
 
 
 
  1. struct User {
  2.     let id: Int
  3.     let name: String
  4. }

假設(shè)我們還有兩個(gè)方法,一個(gè)獲取用戶id列表,另一個(gè)使用id獲取某個(gè)用戶。而且假設(shè)我們想顯示第一個(gè)用戶的名字。

通過我們的實(shí)現(xiàn),我們可以這樣做,使用之前定義的這三個(gè)then。

 
 
 
 
  1. func fetchIds() -> Promise<[Int]> {
  2.     ...
  3. }
  4. func fetchUser(id: Int) -> Promise {
  5.     ...
  6. }
  7. fetchIds()
  8.     .then { ids in // flatMap
  9.         return fetchUser(id: ids[0])
  10.     }
  11.     .then { user in // map
  12.         return user.name
  13.     }
  14.     .then { name in // observe
  15.         print(name)
  16.     }

代碼變得十分易讀、簡(jiǎn)潔,而且沒有嵌套。

結(jié)論本文結(jié)束,希望你喜歡它。

參考資料

[1]gist:

https://gist.github.com/felginep/039ca3b21e4f0cabb1c06126d9164680

[2]Promises in Swift by Khanlou:

http://khanlou.com/2016/08/promises-in-swift/

[3]JavaScript Promises … In Wicked Detail:

https://www.mattgreer.org/articles/promises-in-wicked-detail/

[4]PromiseKit 6 Release Details:

https://promisekit.org/news/2018/02/PromiseKit-6.0-Released/

[5]TDD Implementation of Promises in JavaScript:

https://www.youtube.com/watch?v=C3kUMPtt4hY

[6]Implementing Promises in Swift:

https://felginep.github.io/2019-01-06/implementing-promises-in-swift

本文轉(zhuǎn)載自微信公眾號(hào)「Swift社區(qū)」


文章名稱:一文帶你使用Swift實(shí)現(xiàn)Promise
URL分享:http://www.5511xx.com/article/djpsjdc.html