You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
3.1 KiB

  1. //
  2. // Promise+Then.swift
  3. // then
  4. //
  5. // Created by Sacha Durand Saint Omer on 20/02/2017.
  6. // Copyright © 2017 s4cha. All rights reserved.
  7. //
  8. import Foundation
  9. public extension Promise {
  10. @discardableResult public func then<X>(_ block: @escaping (T) -> X) -> Promise<X> {
  11. let p = registerThen(block)
  12. tryStartInitialPromiseAndStartIfneeded()
  13. return p
  14. }
  15. @discardableResult public func registerThen<X>(_ block: @escaping (T) -> X) -> Promise<X> {
  16. let p = Promise<X>()
  17. synchronize { state, blocks in
  18. switch state {
  19. case let .fulfilled(value):
  20. let x: X = block(value)
  21. p.fulfill(x)
  22. case let .rejected(error):
  23. p.reject(error)
  24. case .dormant, .pending:
  25. blocks.success.append({ t in
  26. p.fulfill(block(t))
  27. })
  28. blocks.fail.append({ e in
  29. p.reject(e)
  30. })
  31. blocks.progress.append({ f in
  32. p.setProgress(f)
  33. })
  34. }
  35. }
  36. passAlongFirstPromiseStartFunctionAndStateTo(p)
  37. return p
  38. }
  39. @discardableResult public func then<X>(_ block: @escaping (T) -> Promise<X>) -> Promise<X> {
  40. tryStartInitialPromiseAndStartIfneeded()
  41. return registerThen(block)
  42. }
  43. @discardableResult public func registerThen<X>(_ block: @escaping (T) -> Promise<X>)
  44. -> Promise<X> {
  45. let p = Promise<X>()
  46. synchronize { state, blocks in
  47. switch state {
  48. case let .fulfilled(value):
  49. registerNextPromise(block, result: value,
  50. resolve: p.fulfill, reject: p.reject)
  51. case let .rejected(error):
  52. p.reject(error)
  53. case .dormant, .pending:
  54. blocks.success.append({ [weak self] t in
  55. self?.registerNextPromise(block, result: t, resolve: p.fulfill,
  56. reject: p.reject)
  57. })
  58. blocks.fail.append(p.reject)
  59. blocks.progress.append(p.setProgress)
  60. }
  61. }
  62. p.start()
  63. passAlongFirstPromiseStartFunctionAndStateTo(p)
  64. return p
  65. }
  66. @discardableResult public func then<X>(_ promise: Promise<X>) -> Promise<X> {
  67. return then { _ in promise }
  68. }
  69. @discardableResult public func registerThen<X>(_ promise: Promise<X>) -> Promise<X> {
  70. return registerThen { _ in promise }
  71. }
  72. fileprivate func registerNextPromise<X>(_ block: (T) -> Promise<X>,
  73. result: T,
  74. resolve: @escaping (X) -> Void,
  75. reject: @escaping ((Error) -> Void)) {
  76. let nextPromise: Promise<X> = block(result)
  77. nextPromise.then { x in
  78. resolve(x)
  79. }.onError(reject)
  80. }
  81. }