Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 使用组合运算符将Future转换为Publisher_Swift_Generics_Combine - Fatal编程技术网

Swift 使用组合运算符将Future转换为Publisher

Swift 使用组合运算符将Future转换为Publisher,swift,generics,combine,Swift,Generics,Combine,我使用的API(Firebase)为其大多数方法调用公开了异步接口。对于我通过自己的API发出的每个请求,如果存在这样的令牌,我希望添加一个用户令牌作为头。我试图使整个过程成为联合收割机中同一管道的一部分 我有以下代码: struct Response<T> { let value: T let response: URLResponse } ... func makeRequest<T: Decodable>(_ req: URLRequest, _

我使用的API(Firebase)为其大多数方法调用公开了异步接口。对于我通过自己的API发出的每个请求,如果存在这样的令牌,我希望添加一个用户令牌作为头。我试图使整个过程成为联合收割机中同一管道的一部分

我有以下代码:

struct Response<T> {
    let value: T
    let response: URLResponse
}

...

func makeRequest<T: Decodable>(_ req: URLRequest, _ decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher<T, Error> {
    var request = req
    return Future<String?, Error> { promise in
        if let currentUser = Auth.auth().currentUser {
            currentUser.getIDToken() { (idToken, error) in
                if error != nil {
                    promise(.failure(error!))
                } else {
                    promise(.success(idToken))
                }
            }
        } else {
            promise(.success(nil))
        }
    }
    .map { idToken -> URLSession.DataTaskPublisher in
        if idToken != nil {
            request.addValue("Bearer \(idToken!)", forHTTPHeaderField: "Authorization")
        }
        return URLSession.shared.dataTaskPublisher(for: request)
    }
    .tryMap { result -> Response<T> in
        let value = try decoder.decode(T.self, from: result.data)
        return Response(value: value, response: result.response)
    }
    .receive(on: DispatchQueue.main)
    .map(\.value)
    .eraseToAnyPublisher()
}
struct响应{
let值:T
let response:URLResponse
}
...
func makeRequest(req:URLRequest,decoder:JSONDecoder=JSONDecoder())->AnyPublisher{
var请求=req
回报未来{承诺未来}
如果让currentUser=Auth.Auth().currentUser{
中的currentUser.getIDToken(){(idToken,错误)
如果错误!=nil{
承诺(.failure(error!))
}否则{
承诺(.success(idToken))
}
}
}否则{
承诺(.success(无))
}
}
.map{idToken->URLSession.DataTaskPublisher位于
如果idToken!=nil{
request.addValue(“Bearer\(idToken!)”,forHTTPHeaderField:“Authorization”)
}
返回URLSession.shared.dataTaskPublisher(用于:请求)
}
.tryMap{result->中的响应
let value=try decoder.decode(T.self,from:result.data)
返回响应(值:value,响应:result.Response)
}
.receive(在:DispatchQueue.main上)
.map(\.value)
.删除任何发布者()
}
尝试对响应数据进行JSON解码时,tryMap运算符中出现错误:

“URLSession.DataTaskPublisher”类型的值没有成员“data”


我还在为联合收割机绞尽脑汁,但不明白我在这里做错了什么。任何帮助都将不胜感激

您正在尝试映射到另一个发布者。大多数情况下,这表明您需要
flatMap
。如果您改用
map
,您将得到一个发布另一个发布者的发布者,这几乎肯定不是您想要的

但是,
flatMap
要求上游发布服务器(promise)与您要映射到的发布服务器具有相同的故障类型。但是,在这种情况下,它们并不相同,因此您需要在数据会话发布服务器上调用
maperro
,以更改其错误类型:

return Future<String?, Error> { promise in
    promise(.failure(NSError()))
}
// flatMap and notice the change in return type
.flatMap { idToken -> Publishers.MapError<URLSession.DataTaskPublisher, Error> in
    if idToken != nil {
        request.addValue("Bearer \(idToken!)", forHTTPHeaderField: "Authorization")
    }
    return URLSession.shared.dataTaskPublisher(for: request)
        // change the error type
        .mapError { $0 as Error } // "as Error" isn't technically needed. Just for clarity
}
.tryMap { result -> Response<T> in
    let value = try decoder.decode(T.self, from: result.data)
    return Response(value: value, response: result.response)
}
.receive(on: DispatchQueue.main)
.map(\.value)
.eraseToAnyPublisher()
返回未来{promise in
承诺(.failure(NSError()))
}
//flatMap并注意返回类型的更改
.flatMap{idToken->publisher.maperor在中
如果idToken!=nil{
request.addValue(“Bearer\(idToken!)”,forHTTPHeaderField:“Authorization”)
}
返回URLSession.shared.dataTaskPublisher(用于:请求)
//更改错误类型
.mapError{$0 as Error}//“as Error”在技术上是不需要的。只是为了清楚起见
}
.tryMap{result->中的响应
let value=try decoder.decode(T.self,from:result.data)
返回响应(值:value,响应:result.Response)
}
.receive(在:DispatchQueue.main上)
.map(\.value)
.删除任何发布者()

您正试图映射到另一个发布者。大多数情况下,这表明您需要
flatMap
。如果您改用
map
,您将得到一个发布另一个发布者的发布者,这几乎肯定不是您想要的

但是,
flatMap
要求上游发布服务器(promise)与您要映射到的发布服务器具有相同的故障类型。但是,在这种情况下,它们并不相同,因此您需要在数据会话发布服务器上调用
maperro
,以更改其错误类型:

return Future<String?, Error> { promise in
    promise(.failure(NSError()))
}
// flatMap and notice the change in return type
.flatMap { idToken -> Publishers.MapError<URLSession.DataTaskPublisher, Error> in
    if idToken != nil {
        request.addValue("Bearer \(idToken!)", forHTTPHeaderField: "Authorization")
    }
    return URLSession.shared.dataTaskPublisher(for: request)
        // change the error type
        .mapError { $0 as Error } // "as Error" isn't technically needed. Just for clarity
}
.tryMap { result -> Response<T> in
    let value = try decoder.decode(T.self, from: result.data)
    return Response(value: value, response: result.response)
}
.receive(on: DispatchQueue.main)
.map(\.value)
.eraseToAnyPublisher()
返回未来{promise in
承诺(.failure(NSError()))
}
//flatMap并注意返回类型的更改
.flatMap{idToken->publisher.maperor在中
如果idToken!=nil{
request.addValue(“Bearer\(idToken!)”,forHTTPHeaderField:“Authorization”)
}
返回URLSession.shared.dataTaskPublisher(用于:请求)
//更改错误类型
.mapError{$0 as Error}//“as Error”在技术上是不需要的。只是为了清楚起见
}
.tryMap{result->中的响应
let value=try decoder.decode(T.self,from:result.data)
返回响应(值:value,响应:result.Response)
}
.receive(在:DispatchQueue.main上)
.map(\.value)
.删除任何发布者()