Controlling flow in task based URLSession

Hi,

We can do quite a bit with AsyncSequences, AsyncStreams, and the async APIs that we could do with Combine. As has been noted, one of the things we can't easily do is regulate flow.

I apologize if this has been asked before, but I'm not looking for a general solution, I'm asking if it might make sense to have a version of URLSession's asynchronous data(from) and friends that includes values for throttle, debounce, and removeDuplicates?

Something like:

func data(from url: [URL], 
          delegate: [URLSessionTaskDelegate? = nil,
          throttle throttleInterval: S.SchedulerTimeType.Stride = 0,
          debounce dueTime: S.SchedulerTimeType.Stride = 0,
          removeDuplicates: Bool = false ) async throws -> ([Data]

Thank you,

Daniel

2 Likes

In order to throttle, debounce or remove duplicates you must have at least two values. That function only returns one data value. Are you referring to the bytes API?

It is within the realms of possibility to build general AsyncSequence implementations of those but debounce and throttle need two things; first a definition of duration of time, and second a way to run two tasks and get the result of the first. Those two primitives are enough to construct those operators and more. The caveat there is that is like saying with a hash and equals function one can construct a dictionary type.

Timeout is however something associated with rate control that it is applicable to one value, but to implement that you would need the same primitives as debounce and throttle. I think early on there was talks of a timeout function for concurrency but it was decided to be held off on until there was a better story for specifying duration than a UInt64 representing nanoseconds (which in my opinion is not the most ergonomic type to represent duration)

Thank you,

This was helpful (I need to adopt you before attempting to write an async book!)

My goal was to find a convenience method for this flow that I might use in Combine -

              $searchTerm
                .dropFirst()
                .debounce(for: 0.25,
                          scheduler: RunLoop.main)
                .removeDuplicates()
                .map(applyFormatting)
                .compactMap(iTunesURL)
                .flatMap {url in
                  URLSession.shared
                    .dataTaskPublisher(for: url)
                }

Your reply has really helped me understand the issues.

Thank you,

Daniel

Terms of Service

Privacy Policy

Cookie Policy