1

I need to execute synchronous requests on API using Swift. Requests must be queued. Meaning, if one is already in progress and it awaits response it must not be canceled or interrupted by the next synchronous request that enters queue or is already in queue.

Requests must be executed in order as they enter queue (FIFO). Next request must not start until previous is finished/completed in the queue.

Also, every single request in queue must be executed until queue is empty. Synchronous requests can enter queue at any time.

I meant to implement a Synchronous API Client as a singleton which contains its own Queue for queued requests. Requests must not stop/freeze UI. UI has to be responsive on user interaction all the time.

I know it can be done with semaphores but, unless you know what your are doing and you are completely sure how semaphores work, it is not the safest or maybe the best way do it. Otherwise, potential bugs and crashes could appear.

I'm expecting successful execution of every synchronous request that enters queue (by FIFO order, regardless if it returns success or an error as a response) and UI updates immediately after.

So, my question is what is the best way to approach and solve this problem?

1

1 Answer 1

2

You can create your own DispatchQueue and put you operations on it as DispatchWorkItems. It is serial per default. Just remember to call your completions on DispatchQueue.main if you plan to update the UI.

John Sundell has a wonderful article about DispatchQueues here:

https://www.swiftbysundell.com/articles/a-deep-dive-into-grand-central-dispatch-in-swift/

Sign up to request clarification or add additional context in comments.

4 Comments

I believe the OP understands all of this. The problem here is that if the task being dispatched is, itself, asynchronous, the serial queue will not wait for that. Hence the OP’s reference to semaphores (which make that network request behave in a synchronous manner). That article you reference also contemplates that, but the OP is right that semaphores are not a great solution, which is why we reach for other solutions, like asynchronous Operation subclasses, promises, Combine, etc.
@Jakob Mygind - thanks for the John Sundell article. It's very helpful. I believe I could also solve this problem using DispatchGroup as shown in the article under the section: Grouping and chaining tasks with DispatchGroup.
@Rob - I agree, that is a great point that the problem here is that if the task being dispatched is, itself, asynchronous, the serial queue will not wait for that. The solution must execute requests one by one as they come and next request must not start until previous is finished/completed in the queue.
@MattCodes Right, dequeueing off your DispatchQueue on the DispatchGroup notify callback, and calling enter() on dequeue and leave()on completion should get the desired functionality, I'd say.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.