Search code examples
closuresrx-swiftdeferred

How to return single.deferred in closure


What am I doing wrong? How do I get the Single from the closure? How can I get value from Alamofire.request?

 func loadImageName(url: URL) -> Single<String> {
    let data = try? Data(contentsOf: url)
    guard let query = data else {
        return .error(Error.notFound)
    }

        ...

    return Single.deferred {
        Alamofire.request(request).responseJSON {
            if let error = $0.error {
                return Single<String>.error(error)
            }

            return Single<String>.just(result)
        }
    }
}

Solution

  • In this case you'll want Single.create.

    This takes a block, which has a single argument. This argument is a function that you can call to pass a SingleEvent, i.e. either a .success(Element) (where Element is String in your case) or an .error.

    The block must return a Disposable. You can construct a Disposable that will do additional work when it gets disposed. In the context of network requests, it makes sense to cancel the request.

    func loadImageName(url: URL) -> Single<String> {
        let data = try? Data(contentsOf: url)
        guard let query = data else {
            return .error(Error.notFound)
        }
    
        // ...
    
        Single.create { single in
            let request = Alamofire.request(request).responseJSON {
                if let error = $0.error {
                    return single(.error(error))
                }
    
                return single(.success(result))
            }
    
            return Disposables.create { request.cancel() }
        }
    }