I am wrapping URLSessionDataTask instances in Observable instances via code similar to that listed below (I have removed the use of generics and replaced them with concrete types to, hopefully, make the example more clear).
// Where the conversion of the datatask to the signal occurs.
func toObservable(url: URL, dataTaskToConvert: (URL, (Result<Data>) -> Void)) -> Observable<Result<Data>> {
let signal = Observable<Result<Data>>()
let value: URLSessionDataTask? = dataTaskToConvert(url) { result in
signal.update(result)
}
return signal
}
// Example API for consumer to make network requests without ugly callbacks.
func fetch(url: URL) -> Observable<Result<Data>> {
return toObservable(url: url, dataTaskToConvert: fetch)
}
// DataTask response handling is transformed to use an API with Interstellar's Result type like so:
func fetch(url: URL, completion: @escaping (Result<Data>) -> Void) -> URLSessionDataTask {
let task = sharedUrlSession.dataTask(with: url) { data, response, error in
if let data = data {
completion(Result.success(data))
return
}
if let error = error {
completion(Result.error(error))
return
}
let sdkError = SDKError.invalidHTTPResponse(response: response)
completion(Result.error(sdkError))
}
task.resume()
return task
}
Unfortunately, I haven't figured out a way to expose the underlying URLSessionDataTask to the client to cancel the request in a clean fashion. I think ideally, there would be somesort of method on the observable to stop the signal. My workaround currently is to return tuple of (URLSessionDataTask, Observable<Result<Data>>) rather than just the Observable so that the client can take advantage of the Observable API provided by Interstellar while also having the ability to cancel the request. However, I find the tuple API ugly to use, as client code would look like the following:
// must access the tuple element at index `1` (or named parameter)
fetch(url: someURL).1.then { data in
// do stuff with data
}.error {
// handle error.
}
I am relatively new to the reactive style of programming, so I am currently unable to figure out what a good strategy for disposing the observable and it's underlying might be. I looked into the section on Disposables in the README for ReactiveKit, but I'm not sure how the same concept would integrate with Interstellar.
Is there a way you might recommend cancelling the URLSessionDataTask? I would be very happy to work on a pull request (with a small bit of guidance to kick me off in the right direction) if you think this feature might be useful.
I am wrapping
URLSessionDataTaskinstances inObservableinstances via code similar to that listed below (I have removed the use of generics and replaced them with concrete types to, hopefully, make the example more clear).Unfortunately, I haven't figured out a way to expose the underlying
URLSessionDataTaskto the client to cancel the request in a clean fashion. I think ideally, there would be somesort of method on the observable to stop the signal. My workaround currently is to return tuple of(URLSessionDataTask, Observable<Result<Data>>)rather than just theObservableso that the client can take advantage of theObservableAPI provided by Interstellar while also having the ability to cancel the request. However, I find the tuple API ugly to use, as client code would look like the following:I am relatively new to the reactive style of programming, so I am currently unable to figure out what a good strategy for disposing the observable and it's underlying might be. I looked into the section on
Disposables in the README for ReactiveKit, but I'm not sure how the same concept would integrate with Interstellar.Is there a way you might recommend cancelling the
URLSessionDataTask? I would be very happy to work on a pull request (with a small bit of guidance to kick me off in the right direction) if you think this feature might be useful.