将' . compactmap '替换为自定义' .decode '



我已经创建了一个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的依赖推到单独的模块。

👍🏻

最新更新