TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Jan 2017 |
SPMSupports SPM | ✗ |
Maintained by Wilson Balderrama.
Ax is a library written in Swift that helps you to control the flow of asynchronous executions in a organized way. Inspired by async library.
For example there could be a case when your asynchronous calls depend each other to run so a naive solution could be nesting your calls like in the example below:
runAsync(afterSeconds: 2, completion: {
let dataFromTask1 = 1
self.runAsync(afterSeconds: 2, completion: {
let dataFromTask2 = 2
self.runAsync(afterSeconds: 2, completion: {
let dataFromTask3 = 3
self.runAsync(afterSeconds: 2, completion: {
let dataFromTask4 = 4
print(dataFromTask1) // 1
print(dataFromTask2) // 2
print(dataFromTask3) // 3
print(dataFromTask4) // 4
})
})
})
})
Nesting your asynchronous calls is a common known problem in programming that the community names it as: callback hell, pyramid of doom.
We should avoid this kind of code because it can lead to some really confusing and difficult-to-read code, it is a bad practice.
That is when it comes in play Ax, it helps you to call your async calls in a linear way giving the impression that you were running synchronous calls:
import Ax
var dataFromTask1 = 0
var dataFromTask2 = 0
var dataFromTask3 = 0
var dataFromTask4 = 0
Ax.serial(
tasks: [
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask1 = 1
done(nil)
}
},
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask2 = 2
done(nil)
}
},
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask3 = 3
done(nil)
}
},
{ done in
self.runAsync(afterSeconds: 2) {
dataFromTask4 = 4
done(nil)
}
}
],
result: { error in // feedback closure
print(dataFromTask1) // outputs 1
print(dataFromTask2) // outputs 2
print(dataFromTask3) // outputs 3
print(dataFromTask4) // outputs 4
}
)
done
is a closure that accepts an NSError?
value, when done
is called with a nil
that means that the task was run successfully and in other hand if done
is called with a NSError
value then all subsequents tasks are ignored and then immediately the result
closure is executed with the error
passed to the done
variable.tasks
and result
are run in DispatchQoS.QoSClass.background
mode, it is up to you if you, for example, want to call the result in the main thread.Initially the supported functions are:
This function help you to make asynchronous calls in a sequence way, running them in an orderly fashion where the first call is run and after this is finished, the next call is run and so on.
Example:
import Ax
var authorId = ""
var authorBooks = [Book]()
Ax.serial(
tasks: [
{ done in
self.getAuthorBy(name: "J. K. Rowling") { error, author in
guard let author = author else {
done(NSError(domain: "AppDomain", code: 434, userInfo: [NSLocalizedDescriptionKey: "didn't get author"]))
return
}
authorId = author.id
done(error)
}
},
{ done in
self.getBooksBy(authorId: authorId, completion: { (error, books: [Book]) in
authorBooks = books
done(error)
})
}
],
result: { error in
if let error = error {
print(error)
return
}
print(authorBooks) // [Book(name: "Harry Potter and the Philosopher\'s Stone"), Book(name: "Harry Potter and the Chamber of Secrets")]
}
)
Helps you to make asynchronous calls in a parallel way, this function will help you when you have a number of fixed calls that you need to perform but it doesn’t matter if they are run all of them at the same time.
Example:
import Ax
let userId = "1"
let profileImageURL = "https://unsplash.it/100"
var userFound: User?
var userImage: UIImage?
Ax.parallel(
tasks: [
{ done in
self.getUserBy(id: userId) { error, user in
guard let user = user else {
done(NSError(domain: "AppDomain", code: 434, userInfo: [NSLocalizedDescriptionKey: "No user found."]))
return
}
userFound = user
done(error)
}
},
{ done in
self.getProfileImageBy(url: profileImageURL) { error, image in
guard let image = image else {
done(NSError(domain: "AppDomain", code: 435, userInfo: [NSLocalizedDescriptionKey: "Image not found."]))
return
}
userImage = image
done(error)
}
}
],
result: { error in
if let error = error {
print(error)
return
}
print(userFound!) // User(name: "Walter While")
print(userImage!) // <UIImage: 0x618000095a90>, {100, 100}
}
)
Ax is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod "Ax"
Once installed just import it in your file that you are working:
import Ax
Wilson Balderrama, [email protected]
Ax is available under the MIT license. See the LICENSE file for more info.