Reputation: 11
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
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
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