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.

118 lines
3.5 KiB

  1. //
  2. // Promise+Recover.swift
  3. // then
  4. //
  5. // Created by Sacha Durand Saint Omer on 22/02/2017.
  6. // Copyright © 2017 s4cha. All rights reserved.
  7. //
  8. import Foundation
  9. extension Promise {
  10. public func recover(with value: T) -> Promise<T> {
  11. let p = newLinkedPromise()
  12. syncStateWithCallBacks(
  13. success: p.fulfill,
  14. failure: { _ in
  15. p.fulfill(value)
  16. }, progress: p.setProgress)
  17. return p
  18. }
  19. public func recover<E: Error>(_ errorType: E, with value: T) -> Promise<T> {
  20. let p = newLinkedPromise()
  21. syncStateWithCallBacks(
  22. success: p.fulfill,
  23. failure: { e in
  24. if errorMatchesExpectedError(e, expectedError: errorType) {
  25. p.fulfill(value)
  26. } else {
  27. p.reject(e)
  28. }
  29. },
  30. progress: p.setProgress)
  31. return p
  32. }
  33. public func recover<E: Error>(_ errorType: E, with value: T) -> Promise<T> where E: Equatable {
  34. let p = newLinkedPromise()
  35. syncStateWithCallBacks(
  36. success: p.fulfill,
  37. failure: { e in
  38. if errorMatchesExpectedError(e, expectedError: errorType) {
  39. p.fulfill(value)
  40. } else {
  41. p.reject(e)
  42. }
  43. },
  44. progress: p.setProgress)
  45. return p
  46. }
  47. public func recover(with promise: Promise<T>) -> Promise<T> {
  48. let p = newLinkedPromise()
  49. syncStateWithCallBacks(
  50. success: p.fulfill,
  51. failure: { _ in
  52. promise.then { t in
  53. p.fulfill(t)
  54. }.onError { error in
  55. p.reject(error)
  56. }
  57. },
  58. progress: p.setProgress)
  59. return p
  60. }
  61. public func recover(_ block:@escaping (Error) throws -> T) -> Promise<T> {
  62. let p = newLinkedPromise()
  63. syncStateWithCallBacks(
  64. success: p.fulfill,
  65. failure: { e in
  66. do {
  67. let v = try block(e)
  68. p.fulfill(v)
  69. } catch {
  70. p.reject(error)
  71. }
  72. }, progress: p.setProgress)
  73. return p
  74. }
  75. public func recover(_ block:@escaping (Error) throws -> Promise<T>) -> Promise<T> {
  76. let p = newLinkedPromise()
  77. syncStateWithCallBacks(
  78. success: p.fulfill,
  79. failure: { e in
  80. do {
  81. let promise = try block(e)
  82. promise.then { t in
  83. p.fulfill(t)
  84. }.onError { error in
  85. p.reject(error)
  86. }
  87. } catch {
  88. p.reject(error)
  89. }
  90. }, progress: p.setProgress)
  91. return p
  92. }
  93. }
  94. // Credits to Quick/Nimble for how to compare Errors
  95. // https://github.com/Quick/Nimble/blob/db706fc1d7130f6ac96c56aaf0e635fa3217fe57/Sources/
  96. // Nimble/Utils/Errors.swift#L37-L53
  97. private func errorMatchesExpectedError<T: Error>(_ error: Error, expectedError: T) -> Bool {
  98. return error._domain == expectedError._domain && error._code == expectedError._code
  99. }
  100. private func errorMatchesExpectedError<T: Error>(_ error: Error,
  101. expectedError: T) -> Bool where T: Equatable {
  102. if let error = error as? T {
  103. return error == expectedError
  104. }
  105. return false
  106. }