Search code examples
iosswiftreactive-programmingcombine

how to handle when there's no body


Usually, in delete request, the response code is 204 (no content)

How'd you handle such using Combine, when there's no body to json decode.

func deleteById(_ id: Int) -> AnyPublisher<Void, Error> {
    var request = URLRequest(url: URL(string: "http://domain/products/\(id)")!)
    request.httpMethod = "DELETE"

    return session.dataTaskPublisher(for: request)
            .map { (data, response) -> AnyPublisher<Void, Error> in
                Just(())
                        .setFailureType(to: Error.self)
                        .eraseToAnyPublisher()
            }
            .eraseToAnyPublisher()
}

Attempt

func deleteById(_ id: Int) -> AnyPublisher<Void, Error> {
    var request = URLRequest(url: URL(string: "http://domain/products/\(id)")!)
    request.httpMethod = "DELETE"

    return session.dataTaskPublisher(for: request)
            .map { _ in return } // return nothing
            .eraseToAnyPublisher()
}

Solution

  • URLSession.dataTaskPublisher gives you a publisher with the Failure type of URLError. The return type of your method says the return value should have an Failure type of just Error.

    Note that flatMap can only change the Failure type to Never (a bit like setFailureType). It can't change it to another Error type. mapError is what changes the failure type.

    return URLSession.shared.dataTaskPublisher(for: request)
        .map { _ in () } // '()' is a value of Void
        .mapError { $0 as Error }
        .eraseToAnyPublisher()
    

    Other things to consider:

    • just returning AnyPublisher<Void, URLError>
    • use ignoreOutput() instead of map to return a AnyPublisher<Never, URLError>. This is a publisher that does not publish any value, only completes.