In most programming languages, most functions are synchronous: a call to the function does all of its business in the same thread of execution. For functions meant to retrieve data, this means the data can be returned by calls to the function.
For an asynchronous function, a call to the function triggers business in some other thread, and that business (usually) does not complete until after the call returns. An asynchronous function that retrieves data via another thread cannot directly return the data to the caller because the data is not necessarily ready by the time the function returns.
In a sense, asynchronous functions are infectious: if a function foo calls an asynchronous function to conclude its business, then foo itself is asynchronous. Once you rely upon an asynchronous function to do your work, you cannot somehow remove the asynchronicity.
When the business initiated by an asynchronous function completes, we may want to run some code in response, so the code run