问题描述
我有一个通用函数用于向服务器发送请求。 现在,在我发送请求之前,我需要检查会话令牌是否已过期并在需要时进行更新。
我的函数是这样的func upload<T: Decodable>(some parameters here) -> AnyPublisher<T,Error>
我想在调用主请求之前检查并更新该函数中的令牌,但在这种情况下,我无法返回 AnyPublisher<T,Error>
func upload<T: Decodable>(some parameters here) -> AnyPublisher<T,Error> {
if shouldUpdatetoken {
let request = // prepare request
let session = // prepare session
return session.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: SometokenObject.self,decoder: JSONDecoder())
// here I wanted to save token and continue with
// the prevIoUs request
// but using .map,.flatMap,.compactMap will not return needed publisher
// the error message I'll post below
.map {
// update token with $0
// and continue with the main request
}
} else {
return upload() // this will return AnyPublisher<T,Error> so it's ok here
}
}
我在使用 .flatMap 时遇到的这个错误
Cannot convert return expression of type 'Publishers.FlatMap<AnyPublisher<T,Error>,Publishers.Decode<Publishers.MapKeyPath<URLSession.DataTaskPublisher,JSONDecoder.Input>,SometokenObject,JSONDecoder>>' (aka 'Publishers.FlatMap<AnyPublisher<T,Data>,JSONDecoder>>') to return type 'AnyPublisher<T,Error>'
.map 也类似。
我添加了另一个返回 AnyPublishershouldUpdatetoken
内部使用
func upload<T: Decodable>(some parameters here) -> AnyPublisher<T,Error> {
if shouldUpdatetoken {
return refreshToken() // returns AnyPublisher<Void,Error>
// Now I need to continue with original request
// and I'd like to use something like
.flatMap { result -> AnyPublisher<T,Error>
upload()
}
// but using .map,.compactMap will not return needed publisher
// the error message I'll post below
} else {
return upload() // this will return AnyPublisher<T,Error> so it's ok here
}
}
对于平面地图:
Cannot convert return expression of type 'Publishers.FlatMap<AnyPublisher<T,AnyPublisher<Void,Error>>' to return type 'AnyPublisher<T,Error>'
对于地图:Cannot convert return expression of type 'Publishers.Map<AnyPublisher<Void,AnyPublisher<T,Error>'
也许我需要改用另一种方法? 我在应用程序周围有很多请求,所以在一个地方更新令牌是个好主意,但怎么做?
这是refreshToken()
函数
func refreshToken() -> AnyPublisher<Void,Error> {
let request = ...
let session = ...
return session.dataTaskPublisher(for: request)
.map(\.data)
.decode(type: SometokenObject.self,decoder: JSONDecoder())
.map {
// saved new token
}
.erasetoAnyPublisher()
}
解决方法
你快到了。您需要 eraseToAnyPublisher()
对返回的发布者进行类型擦除。
请记住,像 .flatMap
(或 .map
和其他人)这样的运算符返回他们自己的发布者,就像您在错误 Publishers.FlatMap<AnyPublisher<T,Error>,AnyPublisher<Void,Error>>
中看到的类型 - 您需要键入擦除:
func upload<T: Decodable>(some parameters here) -> AnyPublisher<T,Error> {
if shouldUpdateToken {
return refreshToken() // returns AnyPublisher<Void,Error>
.flatMap { _ -> AnyPublisher<T,Error> in
upload()
}
.eraseToAnyPublisher() // <- type-erase here
} else {
return upload() // actually "return"
}
}
(并确保您不会在没有任何停止条件的情况下不断地递归调用相同的 upload
函数)