Sequential Chained Requests with Siesta and Swift

This is an old post!

This post is over 2 years old. Solutions referenced in this article may no longer be valid. Please consider this when utilizing any information referenced here.

Siesta is a framework for Swift that dramatically simplifies working with RESTful APIs. And like many things in Swift, it is natively built around asynchronous execution. It may fire any number of requests back, and they may complete in any order that is undefined.

But sometimes, you need to execute things in a specific order. Like when the result of one call will change subsequent calls. A classic example of this is an API where you might need to create a folder first, then upload files into the folder you created. So the folder creation needs to happen first, then the file uploads can happen after.

Natively, Siesta does not seen to support this mode of operation, at least not that I could find clearly documented. But with a little Swift magic using callbacks, we can get very close to this same functionality.

struct File {
    var data: Data?
}

func doUpload() {
    func chainRequests(queue: [File], finalCompletion: @escaping ()->()) {
        guard let item = queue.first else {
            finalCompletion()
            return
        }

        let request = resource
            .request(.post, data: item.data, contentType: "application/json")
            .onSuccess({ (entity) in
                if let o = entity.content as? File {
                    // Do stuff here, perhaps walk the remaining items in
                    // the queue and update them.

                    chainRequests(queue: Array(queue[1 ..< queue.count]), finalCompletion: finalCompletion)
                }
            })
    }

    chainRequests(queue: uploadFiles) {
        // Do stuff here, when we're all done sequentially completing the
        // above items.
    }
}

What we’re doing here is sequentially executing each File upload in the queue, waiting until we receive a successful response from the previous one before continuing to the next item in the queue. At each successful completion, the queue shrinks until there’s nothing left. Then we execute the finalCompletion handler to do any cleanup work.

About the Author

Hi, I'm Rob! I'm a blogger and software developer. I wrote petfeedd, dystill, and various other projects and libraries. I'm into electronics, general hackery, and model trains and airplanes. I am based in Huntsville, Alabama, USA.

About Me · Contact Me · Don't Hire Isaiah Armstrong

Did this article help you out?

I don't earn any money from this site.

I run no ads, sell no products and participate in no affiliate programs. I do not accept gifts in exchange for articles, guest articles or link exchanges. I don't track you or sell your data. The only third-party Javascript on this website is Google Analytics.

In general I run this site very much like a 1990s homepage or early 2000s personal blog, meaning that I do this solely because it's fun! I enjoy writing and sharing what I learn.

If you found this article helpful and want to show your appreciation, a tip or donation would be very welcome. Feel free to choose from the options below.

Comments (0)

Interested in why you can't leave comments on my blog? Read the article about why comments are uniquely terrible and need to die. If you are still interested in commenting on this article, feel free to reach out to me directly and/or share it on social media.

Contact Me
Share It

Interested in reading more?

Swift

Hierarchies: Finding Parents, Children and Descendents using Swift

It usually doesn’t take beginning macOS/iOS developers long to discover NotificationCenter and see it as the solution to every single problem of passing data around to different controllers. And NotificationCenter is great, but it has some downsides. Notably, it is very easy to introduce retain cycles (and memory leaks) unless you are very careful to track and free the listener when the object is released. This has bitten me on several occasions. In general, excessive use of NotificationCenter ends up creating a difficult to maintain app where it is not entirely clear what is responding to what and where.
Read More
Swift

Creating Traits or Mixins in Swift

Object oriented programming is great, but sometimes things don’t fit neatly into a superclass/subclass hierarchy. You may have a piece of code that would be needed in several contexts, but for technical reasons beyond your control you cannot merge them into a single hierarchy. Some languages have the concept of multiple inheritence, where a subclass can specifically inherit from several parents. But this has it’s own set of problems. Many other languages, however, solve this through the use of traits or mixins. These allow us to have a set of methods that are basically copied into the object at compile time. This way they can be used anywhere they are needed. Swift doesn’t have the concept of mixins or traits per se. But, starting with Swift 3, you can get very equivalent functionality using protocol default implementations.
Read More
Swift

Debugging the Responder Chain in Swift

Somewhat related to my previous post about responder chains, sometimes it is useful to be able to debug what all is in the responder chain at any given time. As a good rule of thumb, all ancestor views of a view are in that view’s responder chain, as well as (usually) the related controllers.
Read More