Reputation: 492
In Swift 5.5:
Following Swift Code will get compiler error: "async call in a function that does not support concurrency".
// Swift
func hi() async {
print("hi")
}
func callAsyncHi() {
hi()
}
In Javascript, await is only valid in async function, but calling an async func from a normal func is valid. So following Javascript Code prints "hi" asynchronously.
// Javascript
async function hi() {
console.log("hi")
}
function callAsyncHi() {
hi()
}
callAsyncHi()
I also found an async func cannot be called without await or async let. Why Swift is designed in this way?
Upvotes: 6
Views: 6910
Reputation: 2802
You can invoke async function from normal function by wrapping the asynchronous call inside a task:
func hi() async {
print("hi")
}
func callAsyncHi() {
let task = Task {
await hi()
}
}
This is similar to how you can invoke async methods in java script from synchrnous context, key difference being in Swift you have to explicitly specify it and inside Task
you can invoke more than one async methods.
There are certain reasons behind a design like this. Key reason being in Swift all async methods are associated with tasks and support cooperative cancellation.
Swift concurrency uses a cooperative cancellation model. Each task checks whether it has been canceled at the appropriate points in its execution, and responds to cancellation in whatever way is appropriate.
By requiring async
keyword Swift keeps track of the dependency chain of async calls and propagates cancellation event when it occurs (While as far as I know promises in JS doesn't support cancellation of promises). In the above code, you can invoke cancellation on task
variable by keeping track of it.
Now the second reason, more important in my opinion, is by requiring explicit invocation this makes it easier to review code as I have to check if cancellation for such invocations are properly handled while in case of JS it is harder to pinpoint such misuse.
Upvotes: 12
Reputation: 492
We pass Promises/Tasks around freely and do many things.
But an async function from Swift returns ???.
??? is hidden. I cannot even print its type.
// swift compiler error: Expression is 'async' but is not marked with 'await'
func callAsyncHi() {
Task {
async let tmp = hi()
print(Mirror(reflecting: tmp).subjectType)
await tmp
}
}
I guess there is no ???. So we have to use async func with await.
Upvotes: -4