将替换 .compactMap 与自定义 .decode 结合起来
Combine replace `.compactMap` with custom `.decode`
我创建了一个 AnyPublisher
用于订阅 Firestore 文档,输出类型是 DocumentSnapshot。
我运行是这样的...
firestoreSubscription.subscribe(MyHashable(), "/user/1234567890")
.compactMap { try? [=10=].data(as: UserDoc.self }
这个return的类型是<UserDoc, Never>
,我想保留。
这行得通,但我认为如果我可以在 Publisher 上使用 .decode
功能使其更像 Combiney,那会很酷。
所以我创建了这个...
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
抛出而不是 returning nil
。我想知道,是否可以丢弃 throws 并默认返回到我在使用 .decode
方法时使用的紧凑地图解决方案?
或者...我应该继续使用 .compactMap
吗?
还有... .decode
上的 throw
会结束发布者吗?
will the throw on the .decode end the publisher
是的,这将导致流失败 - 如果您订阅 Firestore 上的更改,这可能不是您想要的
您可以使用 Combine 的 catch
运算符来处理流中的故障
使用你的例子,忽略你会发现的失败和 return 一个 Empty
发布者。
environment.firestoreSubscription.subscribe(userSubscriptionID, "/user/\(state.userID)")
.decode(type: UserDoc.self, decoder: FirestoreDecoder())
.catch{ _ in Empty<UserDoc, Never>().eraseToAnyPublisher() }
好的,将 FirestoreDecoder
更改为...
import Firebase
public struct FirestoreDecoder {
public static func decode<T>(_ type: T.Type) -> (DocumentSnapshot) -> T? where T: Decodable {{
try? [=10=].data(as: type)
}}
}
我能够做到...
firestoreSubscription.subscribe(MyHashable(), "/user/1234567890")
.compactMap(FirestoreDecoder.decode(UserDoc.self))
这与我最初的相似,但将对 Firestore
的依赖推到了单独的模块中。
我创建了一个 AnyPublisher
用于订阅 Firestore 文档,输出类型是 DocumentSnapshot。
我运行是这样的...
firestoreSubscription.subscribe(MyHashable(), "/user/1234567890")
.compactMap { try? [=10=].data(as: UserDoc.self }
这个return的类型是<UserDoc, Never>
,我想保留。
这行得通,但我认为如果我可以在 Publisher 上使用 .decode
功能使其更像 Combiney,那会很酷。
所以我创建了这个...
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
抛出而不是 returning nil
。我想知道,是否可以丢弃 throws 并默认返回到我在使用 .decode
方法时使用的紧凑地图解决方案?
或者...我应该继续使用 .compactMap
吗?
还有... .decode
上的 throw
会结束发布者吗?
will the throw on the .decode end the publisher
是的,这将导致流失败 - 如果您订阅 Firestore 上的更改,这可能不是您想要的
您可以使用 Combine 的 catch
运算符来处理流中的故障
使用你的例子,忽略你会发现的失败和 return 一个 Empty
发布者。
environment.firestoreSubscription.subscribe(userSubscriptionID, "/user/\(state.userID)")
.decode(type: UserDoc.self, decoder: FirestoreDecoder())
.catch{ _ in Empty<UserDoc, Never>().eraseToAnyPublisher() }
好的,将 FirestoreDecoder
更改为...
import Firebase
public struct FirestoreDecoder {
public static func decode<T>(_ type: T.Type) -> (DocumentSnapshot) -> T? where T: Decodable {{
try? [=10=].data(as: type)
}}
}
我能够做到...
firestoreSubscription.subscribe(MyHashable(), "/user/1234567890")
.compactMap(FirestoreDecoder.decode(UserDoc.self))
这与我最初的相似,但将对 Firestore
的依赖推到了单独的模块中。