Questions about Future in Dart - asynchronous

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.

Related

Why Future works after the main function was done?

In the example on dart.dev the Future prints the message after the main function was done.
Why might the Future work after the main function was done? At first glance, after the completion of the main function, the entire work of the program is expected to be completed (and the Future must be cancelled).
The example code:
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info from another service or database.
return Future.delayed(Duration(seconds: 2), () => print('Large Latte'));
}
void main() {
fetchUserOrder();
print('Fetching user order...');
}
The program prints
Fetching user order...
Large Latte
I've expected just the following
Fetching user order...
This has to do with the nature of futures and asynchronous programming. Behind the scenes, Dart manages something called the asynchronous queue. When you initiate a future (either manually like you did with Future.delayed or implicitly by calling a method marked async, that function's execution goes into the queue whenever its execution gets deferred. Every cycle when Dart's main thread is idle, it checks the futures in the queue to see if any of them are no longer blocked, and if so, it resumes their execution.
A Dart program will not terminate while futures are in the queue. It will wait for all of them to either complete or error out.

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();

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

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.

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]);
}

async/await in background in ASP.NET WebApi

Let's suppose i have the following async method that needs fairly long time until completing its work:
void async Task LongWork()
{
await LONGWORK() // ... long work
}
Now, in an web api, i would like to run that work in a background (i.e., i want to return the Http Request after starting that LongWork() but before its completion:
I can think of three approaches to achieve this:
1) public async Task<string> WebApi()
{
... // do another work
await Task.Factory.StartNew(() => LongWork());
return "ok";
}
2) public async Task<string> WebApi()
{
... // do another work
await Task.Factory.StartNew(async () => await LongWork());
return "ok";
}
3) public async Task<string> WebApi()
{
... // do another work
Task.Factory.StartNew(async () => await LongWork());
return "ok";
}
Q1: What's the difference between approach #1 and #2?
Q2: What is the right way to, in the ASP.NET world, run a method (in this example, LongWork() containing some async/await pairs in a background thread?
In particular, in #3, there's no "await" before Task.Factory.StartNew(async () => await LongWork()). Is it fine?
Thanks!
Q1: What's the difference between approach #1 and #2?
#1 has less overhead. That is the only difference.
Q2: What is the right way to, in the ASP.NET world, run a method (in this example, LongWork() containing some async/await pairs in a background thread?
None of the options you provided. For one thing, they all use Task.Factory.StartNew without specifying a TaskScheduler, which is dangerous (as I describe on my blog). They should use Task.Run instead. However, even if you use Task.Run, you will run into a more serious underlying problem.
The underlying problem is this: the HTTP protocol is centered around each request having exactly one matching response. When an HTTP server (such as ASP.NET) knows that there are no outstanding requests, it will make assumptions like "it's safe to recycle the worker process".
I describe this problem in more detail on my blog. Also in that blog post is a type BackgroundTaskManager that registers background tasks with the ASP.NET runtime and (correctly) executes them via Task.Run. You should only use BackgroundTaskManager if you read the blog post and understand and accept that this is still dangerous and unsafe.
A far better (read: more reliable) solution is to first write out a representation of the work to be done to persistent storage (e.g., an Azure queue) and have an independent backend process (e.g., an Azure worker role) that processes requests from the queue.

Resources