Skip to content

Commit e246d86

Browse files
add ability to specify callback queue and have chain return value as funnel to callback queue
1 parent e0e0664 commit e246d86

5 files changed

Lines changed: 44 additions & 12 deletions

File tree

Sources/Apollo/FinalizingInterceptor.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public class FinalizingInterceptor: ApolloInterceptor {
2222
return
2323
}
2424

25-
completion(.success(parsed))
25+
chain.returnValueAsync(value: parsed,
26+
completion: completion)
2627
}
2728
}

Sources/Apollo/LegacyCacheReadInterceptor.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ public class LegacyCacheReadInterceptor: ApolloInterceptor {
4747
response: response,
4848
completion: completion)
4949
case .success(let graphQLResult):
50-
completion(.success(graphQLResult as! ParsedValue))
50+
chain.returnValueAsync(value: graphQLResult as! ParsedValue,
51+
completion: completion)
5152
}
5253

5354
// In either case, keep going asynchronously
@@ -65,7 +66,8 @@ public class LegacyCacheReadInterceptor: ApolloInterceptor {
6566
completion: completion)
6667
case .success(let graphQLResult):
6768
// Cache hit! We're done.
68-
completion(.success(graphQLResult as! ParsedValue))
69+
chain.returnValueAsync(value: graphQLResult as! ParsedValue,
70+
completion: completion)
6971
}
7072
}
7173
case .returnCacheDataDontFetch:
@@ -78,7 +80,8 @@ public class LegacyCacheReadInterceptor: ApolloInterceptor {
7880
response: response,
7981
completion: completion)
8082
case .success(let result):
81-
completion(.success(result as! ParsedValue))
83+
chain.returnValueAsync(value: result as! ParsedValue,
84+
completion: completion)
8285
}
8386
}
8487
}

Sources/Apollo/LegacyCacheWriteInterceptor.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ public class LegacyCacheWriteInterceptor: ApolloInterceptor {
5858
preconditionFailure(String(describing: error))
5959
}
6060
}
61-
completion(.success(result as! ParsedValue))
61+
62+
chain.returnValueAsync(value: result as! ParsedValue,
63+
completion: completion)
6264
}.catch { error in
6365
chain.handleErrorAsync(error,
6466
request: request,

Sources/Apollo/NetworkFetchInterceptor.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ public class NetworkFetchInterceptor: ApolloInterceptor, Cancellable {
2222
do {
2323
urlRequest = try request.toURLRequest()
2424
} catch {
25-
completion(.failure(error))
25+
chain.handleErrorAsync(error,
26+
request: request,
27+
response: response,
28+
completion: completion)
2629
return
2730
}
2831

Sources/Apollo/RequestChain.swift

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import Foundation
2+
#if !COCOAPODS
3+
import ApolloCore
4+
#endif
25

36
public class RequestChain: Cancellable {
47

@@ -9,21 +12,26 @@ public class RequestChain: Cancellable {
912

1013
private let interceptors: [ApolloInterceptor]
1114
private var currentIndex: Int
12-
public private(set) var isCancelled: Bool = false
15+
public private(set) var callbackQueue: DispatchQueue
16+
public private(set) var isCancelled = Atomic<Bool>(false)
1317

1418
/// Helper var for readability in guard statements
1519
public var isNotCancelled: Bool {
16-
!self.isCancelled
20+
!self.isCancelled.value
1721
}
1822

1923
/// Something which allows additional error handling to occur when some kind of error has happened.
2024
public var additionalErrorHandler: ApolloErrorInterceptor?
2125

2226
/// Creates a chain with the given interceptor array.
2327
///
24-
/// - Parameter interceptors: The interceptors to use.
25-
public init(interceptors: [ApolloInterceptor]) {
28+
/// - Parameters:
29+
/// - interceptors: The array of interceptors to use.
30+
/// - callbackQueue: The `DispatchQueue` to call back on when an error or result occurs. Defauls to `.main`.
31+
public init(interceptors: [ApolloInterceptor],
32+
callbackQueue: DispatchQueue = .main) {
2633
self.interceptors = interceptors
34+
self.callbackQueue = callbackQueue
2735
self.currentIndex = 0
2836
}
2937

@@ -86,7 +94,7 @@ public class RequestChain: Cancellable {
8694

8795
/// Cancels the entire chain of interceptors.
8896
public func cancel() {
89-
self.isCancelled = true
97+
self.isCancelled.value = true
9098

9199
// If an interceptor adheres to `Cancellable`, it should have its in-flight work cancelled as well.
92100
for interceptor in self.interceptors {
@@ -132,7 +140,9 @@ public class RequestChain: Cancellable {
132140
}
133141

134142
guard let additionalHandler = self.additionalErrorHandler else {
135-
completion(.failure(error))
143+
self.callbackQueue.async {
144+
completion(.failure(error))
145+
}
136146
return
137147
}
138148

@@ -143,4 +153,17 @@ public class RequestChain: Cancellable {
143153
response: response,
144154
completion: completion)
145155
}
156+
157+
public func returnValueAsync<ParsedValue: Parseable>(
158+
value: ParsedValue,
159+
completion: @escaping (Result<ParsedValue, Error>) -> Void) {
160+
161+
guard self.isNotCancelled else {
162+
return
163+
}
164+
165+
self.callbackQueue.async {
166+
completion(.success(value))
167+
}
168+
}
146169
}

0 commit comments

Comments
 (0)