使用 Swift Combine 不返回的 POST 请求不适用于 AnyPublisher<Void, Error>

Posted

技术标签:

【中文标题】使用 Swift Combine 不返回的 POST 请求不适用于 AnyPublisher<Void, Error>【英文标题】:POST request using Swift Combine without return doesn't work with AnyPublisher<Void, Error> 【发布时间】:2021-06-14 20:23:11 【问题描述】:

我有一个 POST 请求,向用户发送一条短信,该短信不返回任何内容,只返回状态码。我尝试返回 AnyPublisher 但它不起作用。 enter image description here

这是我的通用请求方法的样子:

func request<T>(_ req: NetworkRequest) -> AnyPublisher<T, NetworkError> where T: Decodable, T: Encodable 
    let sessionConfig = URLSessionConfiguration.default
    sessionConfig.timeoutIntervalForRequest = TimeInterval(req.requestTimeout ?? requestTimeout)

    guard let url = URL(string: req.url) else 
        // Return a fail publisher if the url is invalid
        return AnyPublisher(
            Fail<T, NetworkError>(error: NetworkError.badURL("Invalid Url"))
        )
    
    // We use the dataTaskPublisher from the URLSession which gives us a publisher to play around with.
    return URLSession.shared
        .dataTaskPublisher(for: req.buildURLRequest(with: url))
        .tryMap  output in
            // throw an error if response is nil
            guard output.response is HTTPURLResponse else 
                throw NetworkError.serverError(code: 0, error: "Server error")
            
            return output.data
        
        .decode(type: T.self, decoder: JSONDecoder())
        .mapError  error in
            // return error if json decoding fails
            NetworkError.invalidJSON(String(describing: error))
        
        .eraseToAnyPublisher()

【问题讨论】:

“它不起作用”是什么意思?另外,所有这些中的发布请求在哪里?数据任务不会执行发布请求。 twilioservice .generateCode(to: formattedPhoneNo) .sink(receiveCompletion: (completion) in switch completion case .failure(let error): print("ERROR: (error.localizedDescription)") 案例.finished: return , receiveValue: (res) in print("RESPONSE: (res)") ) .store(in: &cancellables) Xcode 没有指责 post 请求调用有任何错误,错误出在 post 所附图片中提供的实现方法上。 好吧,不要附上图片。请不要有代码图片。如果需要代码来描述问题,请将其发布为代码(文本)。 【参考方案1】:

看起来主要问题是您试图将AnyPublisher&lt;T,NetworkError&gt; 变成AnyPublisher&lt;Void,NetworkError&gt;

你可以这样做:

service.request(request).map  _ in () .eraseToAnyPublisher()

【讨论】:

我之前试过了,但还是报错:Unable to infer type of aclosure parameter '_' in the current context 如果您可以用createRequest 返回的类型更新问题会很有帮助 - 从包含的代码中不清楚相关的泛型将是什么。 它返回一个networkRequest: func createRequest(token: String, environment: BuildEnvironment) -> NetworkRequest ...,它只是一个抽象了url、headers、body、请求超时和http方法的类. 那么request从哪里推断泛型类型? 这里是错误发生的地方: func generateCode(to number: String) -> AnyPublisher let endpoint = TwilioEndpoints.generateCode(number: "+55(number)") let request = endpoint.createRequest(token: token ?? "", environment: environment) return service.request(request)

以上是关于使用 Swift Combine 不返回的 POST 请求不适用于 AnyPublisher<Void, Error>的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中使用 Combine 读取 JSON 错误对象的属性值?

让自定义 Publisher 在 Swift Combine 上的不同 DispatchQueue 上运行

如何使用 Combine + Swift 复制 PromiseKit 风格的链式异步流

使用 Swift 和 Combine 链接 + 压缩多个网络请求

Swift Combine - @Published 属性数组

Swift Combine:如何从发布者列表中创建单个发布者?