Simultaneous dynamic async calls - flutter

I have a dynamic list of strings including codes.
I want to fetch events for each code and then yield to next state.
I have tried Future.wait() but since is dynamic I can not pass a list of async calls.
This is my code so far:
var packagesData = List<BuiltList<Event>>();
for (var packageNumber in packages) {
final packageEvents = await serviceDataSource.fetchPackageEvents(packageNumber);
packagesData.add(packageEvents);
if (packagesData.length == packages.length) {
return persistAllPackagesData(packagesData);
}
}
I wanted to do something similar to a Promise:
Promise.all([
// for loop here
]).then(() => {
console.log('I did everything!');
});

Use a taskList to maintain needed task and use Future.wait
List<Future<int>> taskList = [];
taskList.add(getRandomNumber());
...
Future.wait(taskList)
.then
full code
import 'dart:async';
import 'dart:math';
Future<int> getRandomNumber() async {
var random = new Random();
return random.nextInt(100);
}
void findSmallestNumberInList(List<int> lst) {
print("all numbers are in:");
lst.forEach((l) => print(l));
lst.sort();
int largest = lst.first;
print("The smallest random # we generated was: ${largest}");
}
void main() async {
List<Future<int>> taskList = [];
taskList.add(getRandomNumber());
taskList.add(getRandomNumber());
taskList.add(getRandomNumber());
Future.wait(taskList)
.then((List<int> results) => findSmallestNumberInList(results));
Future.wait([getRandomNumber(), getRandomNumber(), getRandomNumber()])
.then((List<int> results) => findSmallestNumberInList(results));
}

Related

How can i build async method from scratch?

I want to convert sync method to run as asynchronous
Simple example :
Future<void> increment() async {
for (var i = 0; i < 100000000; i++) {
_counter++;
}
}
When I use this code with flutter the app will freeze, because the code content is running as sync, so now I want to know how can I make this code run as async?
i tried to add Future.delayed as following :
Future<void> increment() async {
for (var i = 0; i < 100000000; i++) {
_counter++;
await Future.delayed(const Duration(microseconds: 1));
}
}
But in some scenarios, it will takes too long time!
Is there a better solution?
Use Isolates in Dart for heavy calculations
There is compute constant in Flutter api for top-level and static functions who manage with Isolates by themselves.
Look into this page Concurrency in Dart
Paste the following code into a test.dart file, and see how you can create an async method from scratch using isolates.
import 'dart:io';
import 'dart:isolate';
void main() async {
// Read some data.
final result = await Isolate.run(_readAndParseDart);
print("Called the async function");
}
String _readAndParseDart() {
final fileData = File("test.dart").readAsStringSync();
print('Finished the asynchronous code');
return fileData;
}
Also try this code and notice the difference (which result will be printed first) when we do not use the async/await when calling the asynchronous method:
import 'dart:io';
import 'dart:isolate';
void main() {
// Read some data.
final result = Isolate.run(_readAndParseDart);
print("Called the async function");
}
String _readAndParseDart() {
final fileData = File("test.dart").readAsStringSync();
print('Finished the asynchronous code');
return fileData;
}

Not able to print debug message while unit testing in Flutter

I am testing a pretty straightforward use-case in Flutter. Inside the use-case class, I have a function that I'm invoking from my test. And I want to add some debug print statements to print the value of some variables inside the function of use-case. But it's not getting printed anywhere. How can I achieve this?
The function in Use-case.
Future<Either<Failure, List<Contest>>> call(NoParams params) async {
final result = await repository.getAllContests();
final currentDateTime = DateTime.now();
List<Contest> ongoingContests = [];
result.fold(
(l) => throw ServerException(),
(allContestList) => () {
for (var contest in allContestList) {
var contestStartTime = DateTime.parse(contest.start_time);
var contestEndTime = DateTime.parse(contest.end_time);
print(contestEndTime); //print statement
}
});
return Right(ongoingContests);
}
}
The test function
test('Should return only the ongoing contests', () async {
when(mockHomepageRepository.getAllContests()).thenAnswer((_) async =>
const Right([tContest, tOngoingContest, tUpcomingContest]));
final result = await getOngoingContests(NoParams()); //invoking the function
expect(result, const Right([tOngoingContest]));
verify(mockHomepageRepository.getAllContests());
verifyNoMoreInteractions(MockHomepageRepository());
});

Flutter how to create package with function

I'm trying to make a package. I need to use async function, but I can't use it while building package.
Package Code:
class Sozluk {
wiki(ceviri) async {
var res = await http.Client()
.get(Uri.parse('https://sozluk.gov.tr/gts?ara=$ceviri'));
var body = res.body;
var decoded = jsonDecode(body);
var json = decoded[0];
var sozlukanlam = json["anlamlarListe"][0]["anlam"];
print(sozlukanlam);
return sozlukanlam;
}
}
Test Code:
void main() {
test('köpek', () {
final sozluk = Sozluk();
var cevap = sozluk.wiki('köpek');
print(cevap);
});
}
The print I got:
Instance of 'Future<dynamic>'
You code is missing a lot of pieces. Just because Dart allows you to write code like a sloppy web developer, does not mean you should. Dart is strongly typed, that is an advantage, please use it.
Problems:
ceviri has no explicit type.
wiki has no explicit return type.
wiki is not awaited
Your anonymous method is not async.
More information about Futures, async and await: What is a Future and how do I use it?
Fixing your code as good as possible:
class Sozluk {
Future<TYPE_X> wiki(TYPE_Y ceviri) async {
var res = await http.Client()
.get(Uri.parse('https://sozluk.gov.tr/gts?ara=$ceviri'));
var body = res.body;
var decoded = jsonDecode(body);
var json = decoded[0];
var sozlukanlam = json["anlamlarListe"][0]["anlam"];
print(sozlukanlam);
return sozlukanlam;
}
}
Test Code:
void main() {
test('köpek', () async {
final sozluk = Sozluk();
var cevap = await sozluk.wiki('köpek');
print(cevap);
});
}
Please note that you need to fill in TYPE_X and TYPE_Y, I have no idea which datatypes best represent your data. Is it a number? A text? You decide.
Yout question is unclear.
If you need to print
sozlukanlam
var in test function you need to await your wiki function becaus it is async.
So you could do somthing like that:
void main() {
test('köpek', () async {
final sozluk = Sozluk();
var cevap = await sozluk.wiki('köpek');
print(cevap);
});
}
OR, if test function couldn't bee async
void main() {
test('köpek', () {
final sozluk = Sozluk();
sozluk.wiki('köpek').then((sozlukanlam)=>print(cevap));
});
}

How can I store a Future <dynamic> data for later use within a program in dart/Flutter?

I have the following code that does not work:
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
main(){
String firstTitle = "";
firstTitle = logic().then((list) => getFirstTitle(list)); // I want to store this data into the variable
// firstTitle for later use.
// However my IDE does not recognize the second firstTitle as being linked to the declaration String firstTitle.
}
class MyList {
static var list = [1];
}
logic() async{
final result = await http.get('https://invidio.us/api/v1/search?q=tech+lead');
final data = json.decode(result.body);
final myList = [];
data.forEach((e) {
myList.add({"title": e['title'], 'videoId': e['videoId'], 'duration': e['lengthSeconds'], "date": e['publishedText']});
//print(myList);
});
return myList;
}
String getFirstTitle(aList){
return aList[0]["title"];
}
I understand that we await for the data to be fetched from the source but once it is how can I keep as any variable ex: String instead of having it as a Future.
UPDATE: To better illustrate the problem with the IDE.
Use async await.
main() async {
String firstTitle = "";
List list=[];
list=await logic();
firstTitle = getFirstTitle(list));
}

Is it possible to filter a List with a function that returns Future?

I have a list List<Item> list and a function Future<bool> myFilter(Item).
Is there a way to filter my list using the Future returning function myFilter()?
The idea is to be able to do something like this:
final result = list.where((item) => myFilter(item)).toList();
But this is not possible since where expects bool and not Future<bool>
Since the iteration involves async operation, you need to use a Future to perform the iteration.
final result = <Item>[];
await Future.forEach(list, (Item item) async {
if (await myFilter(item)) {
result.add(item);
}
});
You can iterate over your collection and asynchronously map your value to the nullable version of itself. In asyncMap method of Stream class you can call async methods and get an unwrapped Future value downstream.
final filteredList = await Stream.fromIterable(list).asyncMap((item) async {
if (await myFilter(item)) {
return item;
} else {
return null;
}
}).where((item) => item != null).toList()
You can try bellow:
1, Convert List => Stream:
example:
Stream.fromIterable([12, 23, 45, 40])
2, Create Future List with this function
Future<List<int>> whereAsync(Stream<int> stream) async {
List<int> results = [];
await for (var data in stream) {
bool valid = await myFilter(data);
if (valid) {
results.add(data);
}
}
return results;
}
Here's a complete solution to create a whereAsync() extension function using ideas from the accepted answer above. No need to convert to streams.
extension IterableExtension<E> on Iterable<E> {
Future<Iterable<E>> whereAsync(Future<bool> Function(E element) test) async {
final result = <E>[];
await Future.forEach(this, (E item) async {
if (await test(item)) {
result.add(item);
}
});
return result;
}
}
You can now use it in fluent-style on any iterable type. (Assume the function validate() is an async function defined elsewhere):
final validItems = await [1, 2, 3]
.map((i) => 'Test $i')
.whereAsync((s) async => await validate(s));
Try this:
final result = turnOffTime.map((item) {
if(myFilter(item)) {
return item;
}
}).toList();