Starting tasks sequentially, but asynchronous - asynchronous

I hope that there are someone that can help me with this. I need to read a large set of files, but don't want the UI to freeze meanwhile. My idea is to read one file. Let the user do some work with it, while the rest of the files are loaded. The problem is that although I use async and await, the method performs synchronous.
Below is some of the code:
// Make two tasks, and start the first task
Task task1 = Task.Run(() => controller.LoadExcelSheet(date, firstLasXFile));
Task task2 = new Task(() => controller.LoadExcelFiles(date, fileListLASEX));
// Do something
// Await that the first task ends until the next task starts
await task1.ContinueWith(secondTask => task2.Start());
// Do something else
await task2;
// Do some final stuff

You should never use the Task constructor and almost never use ContinueWith.
If you need to compose two methods, the proper way to do that is with another method. In this case, it can be a local method:
Task task1 = Task.Run(() => controller.LoadExcelSheet(date, firstLasXFile));
Task task2 = LoadExcelFilesAfterTask();
... // Do something
// Await that the first task ends
await task1;
... // Do something else
await task2;
... // Do some final stuff
async Task LoadExcelFilesAfterTask()
{
await task1;
await Task.Run(() => controller.LoadExcelFiles(date, fileListLASEX));
}

Related

How can i wait for a ForEach to finish in Flutter? [duplicate]

Sample code:
Map<String, String> gg = {'gg': 'abc', 'kk': 'kojk'};
Future<void> secondAsync() async {
await Future.delayed(const Duration(seconds: 2));
print("Second!");
gg.forEach((key, value) async {
await Future.delayed(const Duration(seconds: 5));
print("Third!");
});
}
Future<void> thirdAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
print('third');
}
void main() async {
secondAsync().then((_) {
thirdAsync();
});
}
output
Second!
third
Third!
Third!
as you can see i want to use to wait until foreach loop of map complete to complete then i want to print third
expected Output
Second!
Third!
Third!
third
Iterable.forEach, Map.forEach, and Stream.forEach are meant to execute some code on each element of a collection for side effects. They take callbacks that have a void return type. Consequently, those .forEach methods cannot use any values returned by the callbacks, including returned Futures. If you supply a function that returns a Future, that Future will be lost, and you will not be able to be notified when it completes. You therefore cannot wait for each iteration to complete, nor can you wait for all iterations to complete.
Do NOT use .forEach with asynchronous callbacks.
Instead, if you want to wait for each asynchronous callback sequentially, just use a normal for loop:
for (var mapEntry in gg.entries) {
await Future.delayed(const Duration(seconds: 5));
}
(In general, I recommend using normal for loops over .forEach in all but special circumstances. Effective Dart has a mostly similar recommendation.)
If you really prefer using .forEach syntax and want to wait for each Future in succession, you could use Future.forEach (which does expect callbacks that return Futures):
await Future.forEach(
gg.entries,
(entry) => Future.delayed(const Duration(seconds: 5)),
);
If you want to allow your asynchronous callbacks to run concurrently (and possibly in parallel), you can use Future.wait:
await Future.wait([
for (var mapEntry in gg.entries)
Future.delayed(const Duration(seconds: 5)),
]);
See https://github.com/dart-lang/linter/issues/891 for a request for an analyzer warning if attempting to use an asynchronous function as a Map.forEach or Iterable.forEach callback (and for a list of many similar StackOverflow questions).

Does firebase transaction retry run codes beyond the transaction?

If there are more codes/logic outside the transaction that should only be run when the transaction succeeds, will these codes be ran after the retry succeed? See construed example below based on my Express route handler.
app.post('/some/path/to/endpoint', async (req, res) => {
try {
await db.runTransaction(async t => {
const snapshot = t.get(someDocRef);
const data = snapshot.data();
doSomething(snapshot);
return t.update(snapshot.ref, { someChanges });
});
// QUESTION: If transaction retries and succeeds, will the below code run once?
// logic that requires the transaction succeeds
await axios.post(url, data);
res.status(200).send('success');
} catch (e) {
res.status(500).send('system error');
}
});
Appreciate expert views on this. Thanks
You can find the documentation for runTransaction here.
As you can see, runTransaction() returns a Promise. When you await a Promise, and with you code inserted in a try/catch block, if an error is thrown everything after will be ignored, because the flow will go in the catch statement.
So the answer is yes: everything after runTransaction(), the way you wrote it, will not be executed if something goes wrong.

Redux, Redux Toolkit how to wait until dispatch is finished

guys
Like in the subject is there a solution to wait until dispatch action is finished and then dispatch another?
Do I need thunk?
dispatch(someAction());
when someAction is finished dispatch anotherAction()
dispatch(anotherAction());
It really depends on the action. Normal non-thunk actions are synchronous, so in the next line after the dispatch, the first action will already be 100% handled.
If you are dispatching thunk actions there, you can either await or .then(..) the value that is returned by dispatch.
To elaborate on the idea of #phry.
I use redux-toolkit and have this as an example thunk:
export const EXAMPLE_THUNK = createAsyncThunk(
"group/event/example_thunk",
async () => {
// Just resolves after 2 seconds.
return await new Promise((resolve) => setTimeout(resolve, 2000));
}
);
To dispatch another action after the first dispatch, you can simply await the first dispatch. In my example I updated the loading state.
Although this example works, I am not 100% sure this is the best design pattern out there. Many examples I have seen is updating the state is some dispatch has been resolved! Personally I think this is a more clear way of writing my code
const handleChangeStatus = async () => {
setIsLoading(true);
await dispatch(EXAMPLE_THUNK())
// Or dispatch something else.
setIsLoading(false);
};

Wait for nested future functions to finish in Dart [duplicate]

Sample code:
Map<String, String> gg = {'gg': 'abc', 'kk': 'kojk'};
Future<void> secondAsync() async {
await Future.delayed(const Duration(seconds: 2));
print("Second!");
gg.forEach((key, value) async {
await Future.delayed(const Duration(seconds: 5));
print("Third!");
});
}
Future<void> thirdAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
print('third');
}
void main() async {
secondAsync().then((_) {
thirdAsync();
});
}
output
Second!
third
Third!
Third!
as you can see i want to use to wait until foreach loop of map complete to complete then i want to print third
expected Output
Second!
Third!
Third!
third
Iterable.forEach, Map.forEach, and Stream.forEach are meant to execute some code on each element of a collection for side effects. They take callbacks that have a void return type. Consequently, those .forEach methods cannot use any values returned by the callbacks, including returned Futures. If you supply a function that returns a Future, that Future will be lost, and you will not be able to be notified when it completes. You therefore cannot wait for each iteration to complete, nor can you wait for all iterations to complete.
Do NOT use .forEach with asynchronous callbacks.
Instead, if you want to wait for each asynchronous callback sequentially, just use a normal for loop:
for (var mapEntry in gg.entries) {
await Future.delayed(const Duration(seconds: 5));
}
(In general, I recommend using normal for loops over .forEach in all but special circumstances. Effective Dart has a mostly similar recommendation.)
If you really prefer using .forEach syntax and want to wait for each Future in succession, you could use Future.forEach (which does expect callbacks that return Futures):
await Future.forEach(
gg.entries,
(entry) => Future.delayed(const Duration(seconds: 5)),
);
If you want to allow your asynchronous callbacks to run concurrently (and possibly in parallel), you can use Future.wait:
await Future.wait([
for (var mapEntry in gg.entries)
Future.delayed(const Duration(seconds: 5)),
]);
See https://github.com/dart-lang/linter/issues/891 for a request for an analyzer warning if attempting to use an asynchronous function as a Map.forEach or Iterable.forEach callback (and for a list of many similar StackOverflow questions).

Flutter Async/Await Does not work in forEach loop [duplicate]

Sample code:
Map<String, String> gg = {'gg': 'abc', 'kk': 'kojk'};
Future<void> secondAsync() async {
await Future.delayed(const Duration(seconds: 2));
print("Second!");
gg.forEach((key, value) async {
await Future.delayed(const Duration(seconds: 5));
print("Third!");
});
}
Future<void> thirdAsync() async {
await Future<String>.delayed(const Duration(seconds: 2));
print('third');
}
void main() async {
secondAsync().then((_) {
thirdAsync();
});
}
output
Second!
third
Third!
Third!
as you can see i want to use to wait until foreach loop of map complete to complete then i want to print third
expected Output
Second!
Third!
Third!
third
Iterable.forEach, Map.forEach, and Stream.forEach are meant to execute some code on each element of a collection for side effects. They take callbacks that have a void return type. Consequently, those .forEach methods cannot use any values returned by the callbacks, including returned Futures. If you supply a function that returns a Future, that Future will be lost, and you will not be able to be notified when it completes. You therefore cannot wait for each iteration to complete, nor can you wait for all iterations to complete.
Do NOT use .forEach with asynchronous callbacks.
Instead, if you want to wait for each asynchronous callback sequentially, just use a normal for loop:
for (var mapEntry in gg.entries) {
await Future.delayed(const Duration(seconds: 5));
}
(In general, I recommend using normal for loops over .forEach in all but special circumstances. Effective Dart has a mostly similar recommendation.)
If you really prefer using .forEach syntax and want to wait for each Future in succession, you could use Future.forEach (which does expect callbacks that return Futures):
await Future.forEach(
gg.entries,
(entry) => Future.delayed(const Duration(seconds: 5)),
);
If you want to allow your asynchronous callbacks to run concurrently (and possibly in parallel), you can use Future.wait:
await Future.wait([
for (var mapEntry in gg.entries)
Future.delayed(const Duration(seconds: 5)),
]);
See https://github.com/dart-lang/linter/issues/891 for a request for an analyzer warning if attempting to use an asynchronous function as a Map.forEach or Iterable.forEach callback (and for a list of many similar StackOverflow questions).

Resources