我已经创建了一个AnyPublisher
用于订阅Firestore文档,输出类型是DocumentSnapshot。
我是这样运行的…
firestoreSubscription.subscribe(MyHashable(), "/user/1234567890")
.compactMap { try? $0.data(as: UserDoc.self }
返回类型是我想保留的<UserDoc, Never>
这工作,但我认为这将是很酷的,如果我可以使用.decode
功能的出版商,使其更加组合。
所以我创建了这个。
public struct FirestoreDecoder: TopLevelDecoder {
public init() {}
public typealias Input = DocumentSnapshot
public func decode<T>(_ type: T.Type, from: DocumentSnapshot) throws -> T where T : Decodable {
try! from.data(as: type)!
}
}
那么现在我试试这个…
environment.firestoreSubscription.subscribe(userSubscriptionID, "/user/(state.userID)")
.decode(type: UserDoc.self, decoder: FirestoreDecoder())
但是…TopLevelDecoder
抛出而不是返回nil
。我想知道,是否有可能扔掉抛出和默认回到我的紧凑的地图解决方案,我有,而使用.decode
方法?
还是……我应该继续使用.compactMap
吗?
也…….decode
上的throw
会结束发布者吗?
.decode的抛出是否会终止发行者
是的,这会导致流失败——如果你订阅了Firestore上的更改,这可能不是你想要的
可以使用Combine的catch
操作符来处理流
中的错误。使用您的示例,要忽略失败,您将捕获并返回Empty
发布者。
environment.firestoreSubscription.subscribe(userSubscriptionID, "/user/(state.userID)")
.decode(type: UserDoc.self, decoder: FirestoreDecoder())
.catch{ _ in Empty<UserDoc, Never>().eraseToAnyPublisher() }
OK,通过将FirestoreDecoder
更改为这个…
import Firebase
public struct FirestoreDecoder {
public static func decode<T>(_ type: T.Type) -> (DocumentSnapshot) -> T? where T: Decodable {{
try? $0.data(as: type)
}}
}
我能做…
firestoreSubscription.subscribe(MyHashable(), "/user/1234567890")
.compactMap(FirestoreDecoder.decode(UserDoc.self))
这与我一开始的情况类似,但将对Firestore
的依赖推到单独的模块。
👍🏻