Why do functions have to be async in order to use await within them? - asynchronous

If I want to await a function, why does that have to be done in an async function only?
If I have this:
Function myFunc() {
return await myOtherFunc();
}
I get an error saying: “await expression is only allowed within an asynchronous function.”
I can understand if myOtherFunc() had to be asynchronous (it doesn't make sense to await an asynchronous function), but why does it care if the calling function is asynchronous or not. You can have a fork in a process within a synchronous function due to a call to an asynchronous function, right? So then why can’t you await that asynchronous function within the synchronous function?
NOTE: my question is NOT a duplicate of Javascript Await/Async Feature - What if you do not have the await word in the function?.
^ that question is asking what happens if await is not used in an async function. I'm asking why the function has to be async in order to use await. My response to DougBug below explains why they are different.

The picture in the following article might help explain it to you a bit.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/index
The basic idea though is that the async keyword allows the function to yield its execution up to a calling function.
As such any function that implements await must be marked async so that it can traverse back up the calling path until the first caller is only waiting on it to complete what it needs to do.

Related

Questions about Future in Dart

The tutorial on async programming here talks about async await, but avoids discussing the Future API. I could find more information about the Future API here, but still I have some questions. These tutorials made me raise some questions, ideally I should have placed one for each questions, but since they are small and related I preferred to ask them all in one place.
What triggers/starts a Future execution?
From the text I can only conclude that once an async method returns the Future will be immediately triggered by the runtime.
What's the difference between Future.wait() and Future.then().then().then()?
Are return await myFuture; and return myFuture the same?
The text says an async method will return an incomplete Future once it sees an await or a return.
The text says:
Important: Async functions return Futures. If you don’t want your function to return a future, then use a different solution. For example, you might call an async function from your function.
How can we call an async function, get its return value, and not await, thus, not be an async function?
What triggers/starts a Future execution?
The code block for a Future is placed into the event queue, so it's executed when its turn in the event queue comes up. The Flutter in Focus Futures video has some good visuals about how this works.
What's the difference between Future.wait() and Future.then().then().then()?
They are different ways of handling multiple futures, but the differences are subtle. Future.wait handles errors slightly differently, and its values are returned as a list rather than in sequential code blocks, but in practice, the difference might not matter for your situation.
Are return await myFuture; and return myFuture the same?
No. In the first instance, execution is paused at the await until the Future is processed in the event queue. In the second instance, the Future itself is returned to the caller and execution continues as the caller wishes (probably until the Future is given a chance to be handled).
await is a language feature the essentially waits on the Future to complete at that point, whereas return simply returns the Future itself to the caller.
How can we call an async function, get its return value, and not await, thus, not be an async function?
If you need the return value, then you'd call the async function and then use it's Future directly rather than use await. Here's a silly example:
Future<int> getAsyncInt() async {
return 0;
}
void testAsync() {
getAsyncInt().then((value) {
print("Got an async int: $value");
});
}
In the above example, you can see we use an async function, but testAsync does not await the value (rather uses a Future, so the end result is the same).
If you don't need the return value though, you can just call the async function directly though:
Future<int> getAsyncInt() async {
return 0;
}
void testAsync() {
getAsyncInt();
}
In this second case, in fact, getAsyncInt() will indeed be called, even though it's return value is ignored by the caller.
These are good questions, BTW, hope that helps. async/await can be rather mysterious, but thinking of them as event queues really helps to understand in the flow of execution IMHO.

How to call a async method from synchronous method?

I'm trying to call an asynchronous method from a synchronous method like below:
1. public List<Words> Get(string code)
{
Task<List<Words>> taskWords = GetWordsAsync(code);
var result = taskWords.Result;
return result;
}
private async Task<List<Words>> GetWordsAsync(string code)
{
var result = await codeService.GetWordsByCodeAsync(code);
return result;
}
But this lead to a deadlock, await is not getting the results from the method - GetWordsByCodeAsync
I've done a bit of research and came to know that if we are calling an async method from synchronous method we should use Task.Run
When I changed the code like below, it worked:
2. public List<Words> Get(string code)
{
Task<List<Words>> taskWords = Task.Run<List<Words>>(async () => await GetWordsAsync(code);
var result = taskWords.Result;
return result;
}
private async Task<List<Words>> GetWordsAsync(string code)
{
var result = await codeService.GetWordsByCodeAsync(code);
return result;
}
But I didn't get the context, why it caused a deadlock for 1st way and 2nd one worked fine.
I'd like to know:
What's the difference between two ways?
Is second one the correct way to call async method from synchronous method?
Will using the second method also causes a deadlock at some point of time if the result is large? or is it fail proof(safe) method to use?
Also, please suggest any best practices to better do it as I have to do 5 async calls from a synchronous method - just like taskWords, I have taskSentences etc.,
Note: I don't want to change everything to async. I want to call async method from synchronous method.
I don't want to change everything to async. I want to call async method from synchronous method.
From a technical standpoint, this doesn't make sense. Asynchronous means it doesn't block the calling thread; synchronous means it does. So you understand that if you block on asynchronous code, then it's no longer truly asynchronous? The only benefit to asynchronous code is that it doesn't block the calling thread, so if you block on the asynchronous code, you're removing all the benefit of asynchrony in the first place.
The only good answer is to go async all the way. There are some rare scenarios where that's not possible, though.
What's the difference between two ways?
The first one executes the asynchronous code directly and then blocks the calling thread, waiting for it to finish. You're running into a deadlock because the asynchronous code is attempting to resume on the calling context (which await does by default), and presumably you're running this code on a UI thread or in an ASP.NET Classic request context, which only allow one thread in the context at a time. There's already a thread in the context (the one blocking, waiting for the task to finish), so the async method cannot resume and actually finish.
The second one executes the asynchronous code on a thread pool thread and then blocks the calling thread, waiting for it to finish. There is no deadlock here because the asynchronous code resumes on its calling context, which is a thread pool context, so it just continues executing on any available thread pool thread.
Is second one the correct way to call async method from synchronous method?
There is no "correct" way to do this. There are a variety of hacks, each of which has different drawbacks, and none of which work in every situation.
Will using the second method also causes a deadlock at some point of time if the result is large? or is it fail proof(safe) method to use?
It will not deadlock. What it does, though, is execute GetWordsAsync on a thread pool thread. As long as GetWordsAsync can be run on a thread pool thread, then it will work.
Also, please suggest any best practices to better do it
I have written an article on the subject. In your case, if GetWordsAsync is safe to call on a thread pool thread, then the "blocking thread pool hack" is acceptable.
Note that this is not the best solution; the best solution is to go async all the way. But the blocking thread pool hack is an acceptable hack if you must call asynchronous code from synchronous code (again, it's "acceptable" only if GetWordsAsync is safe to call on a thread pool thread).
I would recommend using GetAwaiter().GetResult() rather than Result, in order to avoid the AggregateException wrapper on error. Also, the explicit type arguments are unnecessary, and you can elide async/await in this case:
var taskWords = Task.Run(() => GetWordsAsync(code));
return taskWords.GetAwaiter().GetResult();

Wrap async usage with Meteor

I'm trying to wrap an async function inside my Meteor app.
To make it maximum simple I will try to make a basic example (because all I found was kinda more complex that i actly need).
In my app I am trying to do
console.log("1");
my_func(string_to_display);
console.log("2");
As node is async I get logs 1 and 2 before to see the string i sent to the function.
I tried to call it this way
var my_func_sync = Meteor.wrapAsync(my_fync);
var result = my_func_sync(string_to_display);
Most examples here are more complex, with URLs and calls between server/client/other services. I would like to know if there is a way to wrap a simple function that will only send my string to console. Could anyone give me a most basic example ever please? Would be highly appreciated!
I guess using async await can sort the issue.
async my_funct1(){
console.log("1");
await my_func(string_to_display);
console.log("2");
}
Note that you will need to use async with my_funct1() if you need to use await. This will typically wait for the call to return back from myfunc(string_to_display) to proceed to the next line.

Redux Saga async/await pattern

I'm using async/await throughout my codebase. Because of this my api calls are defined by async functions
async function apiFetchFoo {
return await apiCall(...);
}
I would like to call this function from my saga code. It seems like I can not do this:
// Doesn't work
function* fetchFoo(action) {
const results = await apiFetchFoo();
yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}
However, this does work, and matches the redux saga documentation:
// Does work
function* fetchFoo(action) {
const results = yield call(apiFetchFoo);
yield put({type: "FOOS_FETCHED_SUCCESSFULLY", foos: results});
}
Is this the correct way to use Redux Saga alongside async/await? It is standard to use this generator syntax inside of the saga code, and the async/await pattern elsewhere?
Yes, that's the standard way to use Redux-Saga.
You should never be calling the await function directly inside the saga-generator, because redux-saga is for orchestrating the side-effects. Therefore, any time that you want to run a side-effect you should do it by yielding the side-effect through a redux-saga effect (usually: call or fork). If you do it directly without yielding it through a redux-saga effect, then redux-saga won't be able to orchestrate the side-effect.
If you think about it, the redux-saga generator is completely testable without the need of mocking anything. Also, it helps to keep things decoupled: if your apiFetchFoo returned a promise, the saga would still work the same.
As pointed out by Josep, await cannot be used inside a generator. Instead you need to use an async function. Also, note this is a limitation of async function itself. It is not imposed by redux-saga.
Beyond this, I also wanted to mention that it is a conscious choice by the redux-saga authors to not allow devs to express sagas as async/await functions.
Generators are more powerful than async/await and they allow advanced features of redux-saga like co-ordinating parallel tasks.
Moreover, expressing sagas as generators help us define Effects which are plain objects defining the side effect. Effects makes it very easy to test our sagas.
So, although your working code is fine, maybe not mixing up sagas and async function is a good idea.
Just define your apiFetchFoo to return a promise which resolves with the response to the request. And when this happens your saga will resume with the results.
const apiFetchFoo = () =>
fetch('foo')
.then(res => res.json())
As the previous answers says , Redux saga uses side effects which handles the async within it so the way of doing it , Is using yield and call if calling an API and so on so far
await always work within a function that's declared as async. #thumbRule
async function fetchList () {
let resp = await fetchApi([params]);
}

Can't await work on a computation other than functions in python3.5?

Does it have to be a function we are not blocking ?
Why isn't this working?
async def trivial(L):
await [num**2 for num in L]
So "Object list can't be used in 'await' expression", Am I correct in assuming it's only looking for a function or is there something that's possible to await??
Per the documentation, await will:
Suspend the execution of coroutine on an awaitable object.
You're in a coroutine, but a list is not awaitable, it isn't "a coroutine or an object with an __await__() method."
Note that the list comprehension is fully evaluated, resulting in a list, before it gets passed to await, so there's no work left to be done at that point anyway. If you were doing something more complex than num**2 inside the loop, you could consider rewriting the process as an "asynchronous iterator" and using async for, as follows:
async def trivial(L):
result = []
async for item in process(L):
result.apend(item)
This would allow other pending tasks to be run between iterations of your process over L.

Resources