void main() {
test('simple', () async {
await fakeAsync((async) async {
final stream = Stream.value(42);
print('hi before await');
await stream.toList();
print('hi after await');
});
});
}
stucks forever in the toList line...
I have also tried to call whatever methods, but still stuck forever in the "await" line
test('simple', () async {
await fakeAsync((async) async {
final stream = Stream.value(42);
final future = stream.toList();
print('hi before await');
async.flushMicrotasks();
async.flushTimers();
async.elapse(const Duration(seconds: 10));
async.elapseBlocking(const Duration(seconds: 10));
await future;
print('hi after await');
});
});
I have looked at the implementation of Stream.toList as follows, but it seems quite normal
Future<List<T>> toList() {
List<T> result = <T>[];
_Future<List<T>> future = new _Future<List<T>>();
this.listen(
(T data) {
result.add(data);
},
onError: future._completeError,
onDone: () {
future._complete(result);
},
cancelOnError: true);
return future;
}
Related
In the async codelab:
Ref: https://dart.dev/codelabs/async-await
They have the following snippet:
Future<void> printOrderMessage() async {
print('Awaiting user order...');
var order = await fetchUserOrder();
print('Your order is: $order');
}
Future<String> fetchUserOrder() {
// Imagine that this function is more complex and slow.
return Future.delayed(const Duration(seconds: 4), () => 'Large Latte');
}
void main() async {
countSeconds(4);
await printOrderMessage();
}
Based on the logic of printOrderMessage() I've made a similar function:
void main() async {
int? value;
value = await test();
print(value);
}
Future<int?> test() async{
print('Function has started');
Future.delayed(Duration(milliseconds: 2000), () {
return 4;
});
}
In my case, it prints Function has started null. why doesn't it wait for the value to be populated
Future<int?> test() async {
print('Function has started');
await Future.delayed(Duration(milliseconds: 2000), () {});
return 4;
}
Future<int?> test() async {
print('Function has started');
return Future.delayed(Duration(milliseconds: 2000), () {
return 4;
});
}
I am buiding an app were I want to run a batch operation in firestore and I want to run it in a different isolate. Here is my code for spawning the isolate:
Future<void> _startAnotherIsolate(String mediaUrl) async {
final isolate = await FlutterIsolate.spawn(isolate1,"hello"); // i need to pass 2 more
arguments
Timer(Duration(seconds: 5), () {
print("Pausing Isolate 1");
isolate.pause();
});
Timer(Duration(seconds: 10), () {
print("Resuming Isolate 1");
isolate.resume();
});
Timer(Duration(seconds: 20), () {
print("Killing Isolate 1");
isolate.kill();
});
}
My code for the isolate:
void isolate1(String data1, String data2) async {
await Firebase.initializeApp();
print("changing profile picture: $phone");
Timer.periodic(Duration(seconds: 1), (timer) => print("Timer Running From Isolate 1"));
var db = FirebaseFirestore.instance;
var batch = db.batch();
FirebaseFirestore.instance.collection("posts").doc(phone).collection("userPosts")
.get().then((querySnapshot) {
for (var document in querySnapshot.docs) {
try {
batch.update(document.reference,{'user_image': mediaUrl});
} on FormatException catch (error) {
// If a document ID is unparsable. Example "lRt931gu83iukSSLwyei" is unparsable.
// print("The document ${error.source} could not be parsed.");
return null;
}
}
return batch.commit();
});
}
I have seen This link and this link but they are not helpful
import 'dart:isolate';
class RequiredArgs {
late final SendPort sendPort;
late int id;
RequiredArgs(this.id, this.sendPort);
}
Future<void> main() async {
ReceivePort receivePort = ReceivePort();
RequiredArgs requiredArgs = RequiredArgs(1122, receivePort.sendPort);
Isolate isolate = await Isolate.spawn(download, requiredArgs);
var resp = await receivePort.first;
print(resp);
}
void download(RequiredArgs requiredArgs) {
final SendPort sendPort = requiredArgs.sendPort;
final id = requiredArgs.id;
print(id);
sendPort.send("yes");
}
We pass the value using the RequiredArgs class. Hope my answer helps.
How do you check if an async void method is completed in Dart?
Method 1:
await voidFoo();
print("the above function was completed");
Future<void> voidFoo() async{
await Future.delayed(Duration(seconds:1));
}
Method 2:
Using a boolean variable like this,
bool isCompleted = false;
...
await voidFoo();
Future<void> voidFoo() async{
await Future.delayed(Duration(seconds:1));
isCompleted = true; //assuming isCompleted can be accessed here
}
There are too many methods to do this
i prefer to do this
Future<void> myFunction() async {
await Future.delayed(Duration(seconds: 3)); // your future operation
}
main() async {
await myFunction();
print("finished");
}
You can use dart Completer.
import 'dart:async';
void main() async {
final completer = Completer<String>();
Future<String> getHttpData()async{
return Future.delayed(const Duration(seconds: 1), () => "Future Result");
}
Future<String> asyncQuery()async {
final httpResponse = await getHttpData();
completer.complete(httpResponse);
return completer.future;
}
print('IsCompleted: ${completer.isCompleted}');
await asyncQuery();
print('IsCompleted: ${completer.isCompleted}');
}
Result;
IsCompleted: false
IsCompleted: true
Hello I am trying to run following code, I want to run a specific asynchronous code and show alert dialog until it's running. But the code is not being executed after await showAlertDialog(); this line.
void appendAndRunPythonCode() async {
await showAlertDialog();
await runPythonScript(final_code);
_alertDialogUtils.dismissAlertDialog(context);
}
This is how my showAlertDialog() function is implemented:
Future<void> showAlertDialog() async {
if (!_alertDialogUtils.isShowing) {
await _alertDialogUtils.showAlertDialog(context);
}
}
runPythonCode():
Future<void> runPythonScript(String code) async {
if (inputImg == null) {
ToastUtils.showToastMessage(text: ConstUtils.input_image_empty_notice);
return;
}
if (code.isEmpty) {
ToastUtils.showToastMessage(text: ConstUtils.code_empty);
return;
}
List<String> lines = code.split('\n');
String lastLine = lines.elementAt(lines.length - 4);
if (lastLine.split(' ').elementAt(0).compareTo('outputImage') != 0) {
ToastUtils.showToastMessage(text: ConstUtils.cv_error_line2);
return;
}
data.putIfAbsent("code", () => code);
data.putIfAbsent("inputImg", () => inputImg);
_alertDialogUtils.showAlertDialog(context);
final result = await _channel.invokeMethod("runPythonCVScript", data);
// Add Artifical Delay of 3 seconds..
await Future.delayed(
Duration(seconds: 3),
);
_alertDialogUtils.dismissAlertDialog(context);
setState(
() {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
output = result['textOutput'] ??= "";
error = result['error'] ??= "";
outputImg = (result['graphOutput']);
data.clear();
},
);
}
You shouldn't await the showAlertDialog because runPythonScript won't be executed until the dialog is dismissed.
Remove the await.
Like so:
void appendAndRunPythonCode() async {
showAlertDialog();
await runPythonScript(final_code);
_alertDialogUtils.dismissAlertDialog(context);
}
I recently learned of the fabulous way of waiting for multiple async functions to complete using Future.wait([asyncFuncOne(), asyncFunctwo()])
However, I noticed two different outcomes when running either of these blocks of code. One awaiting each function to finish, the other using Future.wait for parallel processing. What am I doing wrong?
Method 1:
await msm.initProfileData();
await msm.initActivityFeed();
await msm.getRecentlyActiveUsers();
await msm.getRecommendedUsers();
await msm.getGroups();
await msm.getFollowing();
await msm.getFollowers();
Method 2:
await Future.wait([
msm.getFollowing(),
msm.initProfileData(),
msm.initActivityFeed(),
msm.getRecentlyActiveUsers(),
msm.getRecommendedUsers(),
msm.getGroups(),
msm.getFollowers(),
]);
in Method 1, all the async functions complete before my apps home screen appears. In Method 2 the home screen appears before all the async functions complete.
Cheers and thanks in advance.
EDIT: Additional code example.
#override
void initState() {
super.initState();
googleSignIn.onCurrentUserChanged.listen((account) {
handleSignIn(account);
}, onError: (err) {
print('Error signing in: $err');
});
googleSignIn.signInSilently(suppressErrors: false).then((account) {
handleSignIn(account);
}).catchError((err) {
setState(() => _showSignIn = true);
print('Error signing in: $err');
});
}
handleSignIn(GoogleSignInAccount account) async {
if (account != null) {
await createUserInFirestore();
setState(() {
isAuth = true;
});
} else {
setState(() {
isAuth = false;
_showSignIn = true;
});
}
}
createUserInFirestore() async {
final GoogleSignInAccount user = googleSignIn.currentUser;
DocumentSnapshot doc = await usersRef.document(user.id).get();
//...
//do stuff
//...
await someFunc1(); //Method1
// await comeFunc2(); //Method2
//do more stuff
}
someFunc1() async {
msm.asyncfunc1();
msm.asyncfunc2();
}
someFunc2() async {
await Future.wait([
msm.asyncFunc1(),
msm.asyncFunc2(),
]);
}
#override
Widget build(BuildContext context) {
return isAuth ? buildAuthScreen() : buildUnAuthScreen();
}
Using Future.wait(List<Future>) will wait for all the async operations without sequence as mentioned in the docs. While using await consecutively, it'll wait for the first await async operation to finish before running the next await async operation. If you have a prerequisite output before running the next async operation, it's better to use await async in sequence instead.