FlatMorning
FlatMorning

Reputation: 11

Is there a way to queue function calls?

For communication with backend during the checkout process I have the async functions:

create() : Creates the cart on backend. Called when user segues to the checkout page.

update() : Edits the cart on backend. Called when user edits the cart.

confirm() : Confirms purchase on backend. Called when user places the order.

update() is dependent on response from create(), confirm() is dependent on response from create()/update()

The user can call one function while another is unfinished e.g edits cart shortly after segue to checkout page. This causes problems due to the dependencies.

I have currently semi-solved it by using the bools processing, shouldUpdate and shouldConfirm.

Is there a way to achieve by using a queue where the next function call waits until the previous has finished?

var processing = false // Set true when a function is executing
var shouldUpdate = false // Set true when user edits cart
var shouldConfirm = false // Set true when user taps "Purchase"
var checkoutID = ""

func create() {
    processing = true
    APIClient.sharedClient.createShoppingCart() {
    (checkoutID, error) in
       ...
       processing = false // Finished with network call
       if shouldUpdate { // if edit was done while create() is running
           update()
           shouldUpdate = false
       }
       if shouldConfirm { // if user tapped "Purchase" while create() is running
           confirm()
       }
    }
}

func update() { // Called from view controller or create()
    if processing {return}
    processing = true
    APIClient.sharedClient.updateShoppingCart(forCheckoutID: checkoutID) {
    (error) in
       ...
       processing = false // Finished with network call
       if shouldConfirm { // if user tapped "Purchase" while update() is running
           confirm()
       }

    }
}

func confirm() { // Called from view controller or create()/update()
    if processing {return}
    APIClient.sharedClient.confirmPurchase(forCheckoutID: checkoutID) {
    (error) in
       ...
       /// Finish order process
    }
}

Upvotes: 1

Views: 281

Answers (2)

Jatin Garg
Jatin Garg

Reputation: 206

You can use Dispatch Group

let apiDispatchGroup = DispatchGroup()

func asyncCall1() {
    apiDispatchGroup.enter()
    print("Entered")
    DispatchQueue.main.asyncAfter(deadline: .now()+3) {
        /// After 3 Second it will notify main Queue
        print("Task 1 Performmed")
        /// Let's notify
        apiDispatchGroup.leave()
    }

    apiDispatchGroup.notify(queue: .main) {
        /// Perform task 2
        asyncCall2()
    }
}

func asyncCall2() {
    print("Task 2")
}

Upvotes: 1

BananaAcid
BananaAcid

Reputation: 3481

I personally use PromiseKit - Nice article generally here, wrapping async here - and how to promises here

// your stack
var promises = [];

// add to your stack
promises.push(promise); // some promise func, see above links
promises.push(promise2);

// work the stack
when(fulfilled: promiseArray).then { results in
    // Do something
}.catch { error in
    // Handle error
}

Keywords for similar solutions: Promises, Deferred, Async Stacks.


or: You could implement the following:

Have a pool, array of tupel: methodhandler and bool (=executed true)

create a func(1) runs all funcs from the array, in another wrapper function(2) that will set the tupels bool when it is executed.

func(1) will wait till the tupel is changed, and grab the next one.

Upvotes: 1

Related Questions