How do I operate List async by using Dart? - asynchronous

I have a collection, and now I need to iterate through the data in it, and then modify one of the fields, but this modification process is time consuming and requires asynchronous, I do not know how to write this code correctly.
Here are my fake code:
Stream<int> asynchronousNaturalsTo(int n) async* {
yield calculate(n).asStream();
}
Future<int> calculate(int i) async {
// async calculate result. maybe there is some long-running operate.
return Future.value(i + 10);
}
main() async {
// 1. I have a List that contains data needs be calculated by async.
for (int i = 0; i < 3; i++) {
// 2. calculate
var list = await asynchronousNaturalsTo(i);
// 3. finally, use the final result.
print(list);
}
}
How do I write the code?
thx...

Related

Flutter: I want to update an unspecified amount of data in a firebase document

When I want to update an unspecified amount of data in a firebase document, I would like to know to use List.map or other methods to update the data all at once.
FirebaseFirestore.instance.runTransaction((transaction) async {
DocumentReference documentReference =
collectionReference.doc('usera');
DocumentSnapshot ysnapshot = await transaction.get(documentReference);
for (int i = 0; i < profileList.length; i++) {
transaction.update(
documentReference, {profileList[i].value: profileList[i].data});
}
});
You can use List.forEach.
forEach method
void forEach(
void f(
E element
)
)
Applies the function f to each element of this collection in iteration order.
Source
You can update this loop:
for (int i = 0; i < profileList.length; i++) {
transaction.update(documentReference, {profileList[i].value: profileList[i].data});
}
to this:
profileList.forEach((profile) {
transaction.update(documentReference, {profile.value: profileList.data});
});

Dart waiting for an async function to complete without await

I've narrowed my problem down to the below code. I'm new to Dart, and I can't seem to figure out why the code won't move on to printing "done" before print the numbers 1-10.
import 'dart:async';
Future<bool> wait() async {
for(int i = 0; i < 10; i++){
print('$i');
}
return true;
}
Future testAsync() async {
print('starting');
wait();
print('done');
}
main(List<String> arguments){
testAsync();
}
Since there is no await keyword in front of wait(); shouldn't the program execute print('done'); and then print out the numbers? For some reason, it is waiting for wait(); to finish anyway.
This is expected behavior since Dart 2.0.0:
(Breaking) Functions marked async now run synchronously until the first await statement. Previously, they would return to the event loop once at the top of the function body before any code runs (issue 30345).
https://github.com/dart-lang/sdk/blob/stable/CHANGELOG.md
Since you async method does not actually wait on anything, the entire method is therefore executed synchronously.
You can change you code into something like this to get the behavior your want:
import 'dart:async';
Future<bool> wait() async {
await Future.microtask(() {
for (int i = 0; i < 10; i++) {
print('$i');
}
});
return true;
}
Future testAsync() async {
print('starting');
wait();
print('done');
}
main(List<String> arguments) {
testAsync();
}

Wrong order of execution in Flutter asynchronous code

I am having problems with futures in a Flutter app.
void saveCats() async {
var cats = await convertToCats(_rawData);
await DatabaseProvider.db.addCats(cats);
}
Future<List<Cat>> convertToCats(CatList catData) async {
var cats = <Cat>[];
await catData.forEach(key, value) async {
var pos = await calculatePos();
print('This should come first');
cats.add(Cat(name: key, pos: pos);
}
}
Future<int> calculatePos() async {
return await DatabaseProvider.db.calculatePos();
}
database.dart:
Future<void> addCats(List<Cat> cats) async {
print('This should come second');
// Do adding stuff here
}
Future<int> calculatePos() async {
// Some code to calculate the position
return pos;
}
In the above code, the saveCats function is called when a button is tapped. This function converts some raw data to a list of Cat models, and adds them to the database. As part of this conversion process, it calculates the pos of the cat in a list. My problem is that I would expect that, of my two print statements, the one in the forEach loop should come before the one in the addCats database function. But instead they appear in reverse order. Where am I going wrong?
You can't async/await in List.forEach() or Map.forEach() as both of them return void.
Either use
await Future.forEach([1, 2, 3], (num) async {
await asyncMethod(num);
});
or something similar;
https://api.flutter.dev/flutter/dart-async/Future/forEach.html
forEach often doesn't do what you expect, because the provided function runs as a closure.
It's more natural when you want to iterate over a list doing something to each element to use for (or one of the more functional type methods like map).
It's not clear what type CatList is, so this is approximate, but you'll want something more like:
Future<List<Cat>> convertToCats(CatList catData) async {
var cats = <Cat>[];
for (var i = 0; i < catData.length; i++) {
var key = catData[i].key;
var pos = await calculatePos();
print('This should come first');
cats.add(Cat(name: key, pos: pos));
}
return cats;
}
or
Future<List<Cat>> convertToCats(CatList catData) async {
return catData.map(...some mapping function...).toList();
}

SQLite read from SQLITE database in plugin

I need to read values from an SQLite database in my plugin. For that I found the sqlite.jsm module. My problem is I want to make a row as a global variable, but the code used in SQLite (promises and tasks) is asynchronous. Is there a way I can collect information from my database into a global variable?
let iDs = [];
Task.spawn(function* () {
let db = yield Sqlite.openConnection({ path:
permissionFilePath});
try {
let row = yield db.execute(
"SELECT id FROM 'moz_hosts'");
for ( i=0; i < row.length; i++) {
console.log("row["+ i +"] :" +
row[i].getResultByIndex(0));
yield iDs.push(row[i].getResultByIndex(0));
}
}
finally {
yield db.close();
}
});
// Part of the code that doesn't work, because IDs are not yet assigned any values!
console.log("debug");
for (i=0; i<iDs.length; i++) {
yield console.log("iDs ["+i+"] = "+ iDs[i]);
}
First of all, for a Task you only have to yield things that return promises and therefore run asynchronously. There is no need to yield iDs.push(row[i].getResultByIndex(0));, because the push operation will synchronously return the new length of the array. This shouldn't be much of an issue for the code itself though.
Do you really need the ids to be global? Maybe you can refactor your code so that you don't need to save them globally.
If this is not an option, you will have to block all operations that are going to access the ids until the SQL call has completed. You can do this by relying on the fact that Task.spawn() itself will also return a promise. This also has the nice side effect that you don't need the extra global array:
let idsPromise = Task.spawn(function*() {
let ids = [];
let db = yield Sqlite.openConnection({ path: permissionFilePath});
try {
let row = yield db.execute("SELECT id FROM 'moz_hosts'");
for (let i = 0, len = row.length; i < len; i++) {
ids.push(row[i].getResultByIndex(0));
}
// Instead of the loop you can also use:
// ids = row.map(row => row.getResultByIndex(0));
} finally {
yield db.close();
}
return ids;
});
Then, in other parts of your code, when you want the ids you can use:
idsPromise.then(function(ids) {
// Do something with ids
});
Alternatively, you can also get them in a Task:
Task.spawn(function*() {
let ids = yield idsPromise;
});
You can do this multiple times. Once a promise is resolved the then() part will be executed as soon as possible.

how to handle this type of things. using asp.net mvc

I have
public jsonresult update(studentinfo s)
{
for(i=0;i>0;i++)
{
var x = // i am getting some x so i am checking again
if( x != null)
{
var updateuser = student.update(s.student,"","");
**return json(updateuser.ToString());** // if i keep it here i am getting exceptoin saying not all code paths return value bec this return i can not keep it out for loop bec each and evary updateuser i need to return json..
}
}
}
How to overcome this type of things?
What language are you using to write your code? What you've posted doesn't look like any of the valid languages I know for .NET. Here's how the controller action might look in C# (assuming this is the language you are using):
public ActionResult Update(StudentInfo s)
{
// create some collection that will contain all updated users
var updatedUsers = new List<StudentInfo>();
// Revise the loop as it is absolutely not clear from your code
// what you are trying to do. The way you wrote the loop it will
// never execute - for(int i=0; i>0; i++)
for (int i = 0; i < 5; i++)
{
var updatedUser = student.Update(s.student, "", "");
updatedUsers.Add(updatedUser);
}
// return the list of updated users outside the loop so that the compiler
// doesn't complain about paths of the method not returning a value
return Json(updatedUsers);
}
If I understand correctly, you want to return a collection of users. The 'return' keyword does not work like that. You need to return the entire collection at once.

Resources