Problem
Consider the following Python python code:
async def func(x):
return x
# no 'async' before 'def'
def funcA(x):
return func(x + 1)
# 'async' before 'def'
async def funcB(x):
return await func(x + 1)funcA and funcB are equivalent in their effects. Which is better style?
Opinion
I believe funcB is better, even if it may seem redundant. By declaring the whole function async we make it harder for future careless changes to change the return type of the function.
For example:
async def funcB(x):
if x < 0:
return None
return await func(x + 1)
still returns a Promise in all code paths. In funcA, it’s easy to forget wrapping None in a promise.
This reasoning is less relevant to languages with static type checking, where the type system will point out the programmer’s mistake (i.e. inconsistent return type).
More complex case
With a slightly more complex functions, funcA and funcB will no longer equivalent. Consider:
# no 'async' before 'def'
def funcA(x):
print("funcA started")
return func(x + 1)
# 'async' before 'def'
async def funcB(x):
print("funcB started")
return await func(x + 1)
async def call():
promise = funcA()
await tokio.sleep(1)
await promise
promise = funcB()
await tokio.sleep(1)
await promiseThe print in funcA will appear immediately, before the caller sleeps. However, the print in funcB will only appear after await promise because the execution of an async def function does not start before it’s awaited or passed to create_task (see Immediate vs delayed async execution).
Related
Some languages with async def syntax:
- Python python
- JavaScript JavaScript
- Rust