Based on Dart official page When using Async/Wait:
When the app sees the word async it execute the function normally synchronously, until it sees await or return
Note that an async function starts executing right away
(synchronously). The function suspends execution and returns an
uncompleted future when it reaches the first occurrence of any of the
following:
The function’s first await expression (after the function gets the
uncompleted future from that expression).
Any return statement in the function.
The end of the function body.
and when it sees any of them it returns an uncompleted Future and stops executing the async function until it execute all of the other functions, and when all of the other functions are executed, the app goes back to the async function and executes what's inside of it.
Here's a photo from the Dart official page explaining it in more details:
But when I was testing that I tried to add a print statement before returning the future result as you can see in the below code, but the result wasn't as stated in the site, as it's saying that the app stops executing once it sees the word awaitbut the statement: "Async - Hi Called 1st" was printed as you can see before the other functions were executed.
import 'dart:async';
Future<void> print1stAsync() async {
var test = await callAsync();
print(test);
}
main() {
print1stAsync();
print2nd();
print3rd();
print4th();
}
print2nd() {
print('Called 2nd');
}
print3rd() {
print("Called 3rd");
}
print4th() {
print('Called 4th');
}
Future<String> callAsync() {
print("Async - Hi Called 1st");
return Future(() => "Async - Called 1st ");
}
Output:
Async - Hi Called 1st
Called 2nd
Called 3rd
Called 4th
Async - Called 1st
So why is this happening? have I miss understood something?
The app doesn't stop executing, only the execution of the code after await is delayed until the returned Future completes.
You also need to await the call to the async function print1stAsync(), otherwise the execution of main continues after the call to callAsync(); (after the call, not after the Future it returns completes)
main() async {
await print1stAsync();
print2nd();
print3rd();
print4th();
}
Add async to a function also means that this function returns a Future.
There is no way to go back from async to sync. Async is contagious.
await callAsync(); means code below that line within the same function (like print(test); in your example) will be delayed.
It doesn't say anything about code in callAsync() or code that calls print1stAsync();
Related
Keeping a cron job pub/sub function (functions.pubsub.schedule), within a cloud function (functions.https.OnRequest) and exporting it, does not execute.
A complete example is as follows:
export const sayHelloWhen = functions.https.onRequest((request, response) => {
cors(request, response, () => {
const scheduleExpression = request.body.data.scheduleExpression;
functions.logger.log(`Called sayHelloWhen with ${scheduleExpression}`);
functions.pubsub.schedule(scheduleExpression).onRun((context) => {
functions.logger.log(`Executed sayHelloWhen with ${scheduleExpression}`)
});
response.send({
status: "success",
data: `scheduled at ${scheduleExpression}`
})
})
})
The problem is pub/sub does not trigger. Other codes are executed.
I would like to have HTTP request body scheduleExpression bring into pubsub.schedule's parameter. I don't want a static schedule expression in corn job.
In client, I would like to define a schedule expression in client side as follows:
function scheduleFunction() {
const functions = getFunctions();
const sayHello = httpsCallable(functions, "sayHelloWhen");
sayHello({ scheduleExpression: "every 1 minute" }).then((result) => {
// const data = result.data;
console.log("Result:", result);
});
}
The example below works only for a static schedule expression, meaning that a cloud function itself has a fixed schedule expression:
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
console.log('This will be run every 5 minutes!');
return null;
});
It can be exported as cron job trigger and it executes.
But keeping pub/sub cron job function, within onRequest cloud function, as in the first code example, does not execute.
I think it is very interesting what you are trying to do, but I would like to point out that you are missing some steps that could cause your app not to execute the way you need it to.
First, you need to Terminate your HTTP functions
Always end an HTTP function with send(), redirect(), or end(). Otherwise, your function might continue to run and be forcibly terminated by the system. See also Sync, Async and Promises.
When you do not terminate them, you might end up in a deeper level in which the following code will not execute unless the previous code has finished. I would also like to say I have not found any application with nested functions like you are doing.
In the Sync, async, and promises page you can find a very explicative video to understand the lifecycle of your functions, and in the How promises work with functions section we have:
When you return a JavaScript promise to a function, that function keeps running until the promise is resolved or rejected. To indicate that a function has completed its work successfully, the promise should be resolved. To indicate an error, the promise should be rejected. This means you only need to handle errors that you want to.
In addition to all this, I would suggest using a separate file to Organize multiple functions for a more organized code, but this is only a suggestion not really necessary.
Finally, I am concerned about the scheduledExpression parameter, I think if none of the above works, you might want to check and share what this value is.
Is it possible to pass an async method as an async call in Dart?
For example, if I want to simplify this code:
...
void myFunc() async {
await myLib.work();
}
...
RaisedButton(
onPressed: () async { await myFunc(); },
)
to this:
...
void myFunc() async {
await myLib.work();
}
...
RaisedButton(
onPressed: myFunc,
)
Passing myFunc just as a reference and still maintain that each time myFunc is called from onPressed as a callback, it will be an asynchronous call.
In short: Yes. The two pieces of code that you show are almost completely equivalent. Both call myLib.work and complete a future when the call's asynchronous computation completes.
You could probably also just write:
RaisedButton(
onPressed: myLib.work,
)
and it would still do the same thing.
However, I am not absolutely sure I understand what you mean by an "asynchronous call".
Dart function objects are not split into asynchronous functions and non-asynchronous functions that are called differently. They can be split into those returning Futures and those which don't, but you call them the same way. I assume that myLib.work returns a Future. You may then choose to await the result, but that's not part of the call.
Calling a function is not itself asynchronous, it's always synchronous - it returns a value before computation continues. That value might be a Future which will be completed later when an asynchronous computation has completed, but the function returns synchronously.
So, when you bind a void Function() method to the onPressed event, it will eventually call that function, ignore the return value, and continue synchronously.
If that function is myLib.work, then it calls myLib.work and ignores the returned Future. When the asynchronous work of work is done, it will complete the returned future, which nobody will notice.
If the function is myFunc, then it calls myFunc which immediately calls myLib.work and remembers the returned future. Then myFunc synchronously returns a new Future (which is ignored) and starts waiting (because of the await) on the future returned by myLib.work. When that future completes the await is done, and then the myFunc body is done, and finally the new Future is also completed. Again, nobody notices.
If the function is () async => await myFunc() then that function is called. It immediately calls myFunc, which immediately calls myLib.work, which returns a Future that myFunc starts waiting for and then returns a Future, which the function expression starts waiting for and then returns a Future, which is then ignored.
Eventually all these functions are completed, and nobody notices.
"If a future completes and nobody is listening, does it make an event?"
I'm still struggeling with the async/await pattern so I'm here to ask you some precisions.
I saw this page explaining the async/await pattern pretty well. I'm posting here the example that bother me :
import 'dart:async';
Future<String> firstAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
return "First!";
}
Future<String> secondAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
return "Second!";
}
Future<String> thirdAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
return "Third!";
}
void main() async {
var f = await firstAsync();
print(f);
var s = await secondAsync();
print(s);
var t = await thirdAsync();
print(t);
print('done');
}
In this example, each async method is called one after another, so the execution time for the main function is 6 seconds (3 x 2 seconds). However, I don't understand what's the point of asynchronous function if they are executed one after another.
Are async functions not supposed to execute in the background ? Is it not the point of multiple async functions to fastens the process with parrallel execution ?
I think I'm missing something about asynchronous functions and async/await pattern in flutter so if you could explain me that, it would be very appreciated.
Best
Waiting on multiple Futures to complete using Future.wait()
If the order of execution of the functions is not important, you can use Future.wait().
The functions get triggered in quick succession; when all of them complete with a value, Future.wait() returns a new Future. This Future completes with a list containing the values produced by each function.
Future
.wait([firstAsync(), secondAsync(), thirdAsyncC()])
.then((List responses) => chooseBestResponse(responses))
.catchError((e) => handleError(e));
or with async/await
try {
List responses = await Future.wait([firstAsync(), secondAsync(), thirdAsyncC()]);
} catch (e) {
handleError(e)
}
If any of the invoked functions completes with an error, the Future returned by Future.wait() also completes with an error. Use catchError() to handle the error.
Resource:https://v1-dartlang-org.firebaseapp.com/tutorials/language/futures#waiting-on-multiple-futures-to-complete-using-futurewait
The example is designed to show how you can wait for a long-running process without actually blocking the thread. In practice, if you have several of those that you want to run in parallel (for example: independent network calls), you could optimize things.
Calling await stops the execution of the method until the future completes, so the call to secondAsync will not happen until firstAsync finishes, and so on. If you do this instead:
void main() async {
var f = firstAsync();
var s = secondAsync();
var t = thirdAsync();
print(await f);
print(await s);
print(await t);
print('done');
}
then all three futures are started right away, and then you wait for them to finish in a specific order.
It is worth highlighting that now f, s, and t have type Future<String>. You can experiment with different durations for each future, or changing the order of the statements.
If anyone new in this problem use the async . Dart has a function called FutureGroup. You can use it to run futures in parallel.
Sample:
final futureGroup = FutureGroup();//instantiate it
void runAllFutures() {
/// add all the futures , this is not the best way u can create an extension method to add all at the same time
futureGroup.add(hello());
futureGroup.add(checkLocalAuth());
futureGroup.add(hello1());
futureGroup.add(hello2());
futureGroup.add(hello3());
// call the `.close` of the group to fire all the futures,
// once u call `.close` this group cant be used again
futureGroup.close();
// await for future group to finish (all futures inside it to finish)
await futureGroup.future;
}
This futureGroup has some useful methods which can help you ie. .future etc.. check the documentation to get more info.
Here's a sample usage Example One using await/async and Example Two using Future.then.
you can always use them in a single future
final results = await Future.wait([
firstAsync();
secondAsync();
thirdAsync();
]);
results will be an array of you return type. in this case array of strings.
cheers.
Try this resolve.
final List<Future<dynamic>> featureList = <Future<dynamic>>[];
for (final Partner partner in partnerList) {
featureList.add(repository.fetchAvatar(partner.uid));
}
await Future.wait<dynamic>(featureList);
If want parallel execution you should switch to multi thread concept called Isolates
mix this with async/await concepts . You can also check this website for more
https://buildflutter.com/flutter-threading-isolates-future-async-and-await/
Using async / await like that is useful when you need a resource before executing the next task.
In your example you don't do really useful things, but imagine you call firstAsync, that gives you a stored authorization token in your phone, then you call secondAsync giving this token get asynchronously and execute an HTTP request and then checking the result of this request.
In this case you don't block the UI thread (user can interact with your app) and other tasks (get token, HTTP request...) are done in background.
i think you miss understood how flutter works first flutter is not multi threaded.....!
second if it isn't multi threaded how can it executes parallel tasks, which doesnt happen....! here is some links that will help you understand more https://webdev.dartlang.org/articles/performance/event-loop
https://www.dartlang.org/tutorials/language/futures
flutter doesn't put futures on another thread but what happens that they are added to a queue the links that i added are for event loop and how future works. hope you get it , feel free to ask me :)
What is the correct pattern to consume a highland stream using an async function? It seems the .each method does not work with an node-style async function wrapped using wrapCallback.
I would like to do something like the following. Note that I would like to catch errors generated in the .each function as well and trigger a .done function when all async consumption is done.
function asyncConsume(item,cb) {
// perform async operation based on data stream here
return cb(null,item);
}
var wrappedFunction = _.wrapCallback(asyncConsume);
highlandStream.each(wrappedFunction).done('All successfully done!')
.stopOnError(function(err) {
console.log('This error handler catches errors in .each() as well.');
});
Thank you.
As far as I know, you can only use an async function with Highland map function (after the function has been wrapCallbacked). The map does not actually call the function, so you need a Highland series or parallel call to follow and actually handle the calls.
I think you want flatMap here because you are transforming your items into a new stream:
highlandStream
.flatMap(function(item) {
return wrappedFunction(item);
}).each(someFn).done('All successfully done!')
.stopOnError(function(err) {
console.log('This error handler catches errors in .each() as well.');
});
I'm trying to grok how C# 5's new async feature works. Suppose I want to develop an atomic increment function for incrementing an integer in a fictitious IntStore. Multiple calls are made to this function in one thread only.
async void IncrementKey(string key) {
int i = await IntStore.Get(key);
IntStore.Set(key, i+1);
}
It seems to me that this function is flawed. Two calls to IncrementKey could get the same number back from IntStore (say 5), and then set it to 6, thus losing one of the increments?
How could this be re-written, if IntStore.Get is asynchronous (returns Task) in order to work correctly?
Performance is critical, is there a solution that avoids locking?
If you are sure you are calling your function from only one thread, then there shouldn't be any problem, because only one call to IntStore.Get could be awaiting at at time. This because:
await IncrementKey("AAA");
await IncrementKey("BBB");
the second IncrementKey won't be executed until the first IncrementKey has finished. The code will be converted to a state machine. If you don't trust it, change the IntStore.Get(key) to:
async Task<int> IntStore(string str) {
Console.WriteLine("Starting IntStore");
await TaskEx.Delay(10000);
return 0;
}
You'll see that the second Starting IntStore will be written 10 seconds after the first.
To quote from here http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx The “await” operator ... means “if the task we are awaiting has not yet completed then sign up the rest of this method as the continuation of that task, and then return to your caller immediately; the task will invoke the continuation when it completes.”