Swift Combine:发送值后发送完成



我正在为我的网络模块进行缓存。我的模块将为每个请求向调用者返回一个AnyCancallable。如果缓存的数据不可用,我使用URLSession.dataTaskPublisher,它可以处理两个事件:数据接收和完成。如果缓存的数据可用,我将使用CurrentValueSubject创建要返回的AnyCancallable。我发送了关于这个主题的两个事件,但在调用方,它只在完成时得到通知,没有数据。

cacheSubject.send(cachedData.data)
cacheSubject.send(completion: Subscribers.Completion<Error>.finished)

删除完成发送,现在它可以接收数据,但没有完成通知。

有人能告诉我我在这里做错了什么吗?

这是完整的文件,以防你们需要:

public class SSNetworkManager {
public static let shared = SSNetworkManager()

private var cache: [String: CachedData] = [:]
private let cacheSubject = CurrentValueSubject<Data, Error>(Data())

@discardableResult public func makeServiceCall<D: Decodable>(forRequest request: SSNetworkRequest<D>, onMainThread: Bool = true) -> AnyPublisher<D, Error>? {
guard let urlRequest = request.urlRequest else {
return nil
}

var cancelable: AnyPublisher<Data, Error>

if let url = urlRequest.url?.absoluteString,
let cachedData = cache[url],
cachedData.isValid {
cancelable = cacheSubject.eraseToAnyPublisher()
cacheSubject.send(cachedData.data)
cacheSubject.send(completion: Subscribers.Completion<Error>.finished)
} else {
cancelable = URLSession.shared.dataTaskPublisher(for: urlRequest).tryMap {[weak self] (data, response) -> Data in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
throw SSNetworkError(httpCode: (response as? HTTPURLResponse)?.statusCode ?? 0, data: data)
}
if request.shouldCacheNow,
let url = urlRequest.url?.absoluteString {
self?.cache[url] = CachedData(data: data, expirationTime: request.cacheExpirationTime)
}
return data
}.eraseToAnyPublisher()
}

if onMainThread {
return cancelable
.receive(on: RunLoop.main)
.decode(type: D.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
} else {
return cancelable
.decode(type: D.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
}
}
fileprivate struct CachedData {
let data: Data
let expirationTime: Date

var isValid: Bool {
return Date().compare(expirationTime) != .orderedDescending
}
}

这不是使用主题的正确情况。相反,返回与每个案例相关的发布者:

public class SSNetworkManager {
// ...

public func makeServiceCall<D: Decodable>(
forRequest request: SSNetworkRequest<D>, 
onMainThread: Bool = true
) -> AnyPublisher<D, Error>? {
// consider just returning Empty().eraseToAnyPublisher() instead of nil
guard let urlRequest = request.urlRequest else {
return nil
}
var resultPublisher: AnyPublisher<D: Error>

if let url = urlRequest.url?.absoluteString,
let cachedData = cache[url],
cachedData.isValid {
resultPublisher = Just(cachedData.data)
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
} else {
resultPublisher = URLSession.shared
.dataTaskPublisher(for: urlRequest)
.tryMap { ... }
.decode(type: D.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
return onMainThread
? resultPublisher
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
: resultPublisher
.eraseToAnyPublisher()
}
}

相关内容

  • 没有找到相关文章

最新更新