I have two functions
callee() async {
// do something that takes some time
}
caller () async {
await callee();
}
In this scenario, caller()
waits till callee()
finishes. I don't want that. I want caller()
to complete right after invoking callee()
. callee()
can complete whenever in the future, I don't care. I just want to start it just like a thread and then forget about it.
Is this possible?
Rule: no-async-without-awaitFunctions marked async must contain an await or return statement.
In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously. Code after each await expression can be thought of as existing in a .then callback.
The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.
The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.
When you call the callee
function, it returns a Future
. The await
then waits for that future to complete. If you don't await the future, it will eventually complete anyway, but your caller
function won't be blocked on waiting for that. So, you can just do:
caller() {
callee(); // Ignore returned Future (at your own peril).
}
If you do that, you should be aware of what happens if callee
fails with an error. That would make the returned future complete with that error, and if you don't listen on the future, that error is considered "uncaught". Uncaught errors are handled by the current Zone
and the default behavior is to act like a top-level uncaught error which may kill your isolate.
So, remember to handle the error.
If callee
can't fail, great, you're done (unless it fails anyway, then you'll have fun debugging that).
Actually, because of the risk of just forgetting to await a future, the highly reocmmended unawaited_futures
lint requires that you don't just ignore a returned future, and instead wants you to do unawaited(callee());
to signal that it's deliberate. (The unawaited
function can be imported from package:meta
and will be available from the dart:async
library in SDK version 2.14).
The unawaited
function doesn't handle errors though, so if you can have errors, you should do something more.
You can handle the error locally:
caller() {
callee().catchError((e, s) {
logErrorSomehow(e, s);
});
}
(Since null safety, this code only works if the callee()
future has a nullable value type. From Dart 2.14, you'll be able to use callee().ignore()
instead, until then you can do callee().then((_) => null, onError: (e, s) => logErrorSomehow(e, s));
instead.)
or you can install an error handling zone and run your code in that:
runZoned(() {
myProgram();
}, onError: logErrorSomehow);
See the runZoned function and it's onError
parameter.
Sure, just omit await
. This way callee()
is called immediately and when an async operation is called the call will be scheduled in the event queue for later execution and caller()
is continued immediately afterwards.
This isn't like a thread though. As mentioned processing is enqueued to the event queue which means it won't be executed until the current task and all previously enqueued tasks are completed.
If you want real parallel execution you need to utilize isolates.
See also
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With