How to resolve a Future in flutter (dart)? - flutter

I want to write a functions which returns until an upload has been finished. If it is possible it would be good if I could also add a timeout.
waitForUpload() async {
uploader.result.listen((result) {
// return waitForUpload
}
}
I just don't find how to write this in dart. To make it more clear: In JS the code would look like this:
async waitForUpload() {
return new Promise((resolve) => {
uploader.result.listen((result) {
resolve();
});
});
}

Using a Completer would be more straightforward.
Future time(int time) async {
Completer c = new Completer();
new Timer(new Duration(seconds: time), (){
c.complete('done with time out');
});
return c.future;
}

Stream.single implements the behavior I want. Looking at implementation, you can see future._complete(result); is called inside the listen method which resolves the future.

Related

Run multiple asyn function flutter one after one flutter

hello I want have to run two functions(Function1() and Function2()) and store value of these returns and run third function. But some time according to condition Function1() or Function2() or both not be run.
if(condition1){
await Function1();
}
if(condition2){
await Function2();
}
await Functon3();
I try as above but Function3() run simultaneously with Function1() or with Function2().
My Function1() code looks like following...
Future Function1() async {
apiService
.apiFileUpload()
.then((value) async {
///codes goes here
}).catchError((error) {
print('EEEE: ' + error.toString());
});
}
If anything not clear please let me know in the comment section.
Please do not use .then() in combination with async/await. It is technically possible, but it takes some skill to get it right, so why make it hard on yourself. Stick with one way of doing it, use either one or the other. You mixed it up and through a slight oversight, your Function1 does not actually wait on it's result. It just returns, with the function still running in the then block. So you await it, but that does not help.
Since you are using await already, stick with that and remove .then() from your repertoire for now:
Future Function1() async {
try {
final value = await apiService.apiFileUpload();
///codes goes here
} catch(error) {
print('EEEE: ' + error.toString());
}
}
You can use await
Future Function1() async {
try{
final value = await apiService
.apiFileUpload();
final value2 = await secondFuntion();
///add more and condition on values
} catch(e){
.....
}
}
from your question you need to tell the compiler to stop on particular task with await and avoid using then function it will never stop your compiler
your future fuction:
Future Function1() async {
apiService
.apiFileUpload()
.then((value) async {
///codes goes here
}).catchError((error) {
print('EEEE: ' + error.toString());
});
}
Modified Future func
Future Function1() async {
var result = await apiService.apiFileUpload();
if(result == success){
// code goes here
}else{
//you can show your error here
}
}

Dart Future wait to complete before calling another Future

Looking for help here guys. I have 2 Futures that populate data in sqflite. I need one (_insertInitialData()) to finish first before calling the second one (_insertAdditionalData()). I have done it this way, but it's not working. It first does the re-recreation of the DB as expected, then both _insertInitialData() and _insertAdditionalData() not in the order I expected. I have tried .whenComplete and calling here _insertAdditionalData() and also have tried different ways that I think should work but nothing.
This is just something I'm doing for fun but still I'd like to know what I'm doing wrong.
TIA
Future<void> _insertAdditionalData() async{}
void populateDB() {
try {
final localDB = LocalDatabase.instance;
Future.wait([localDB.dropDB(recreateDB: true)]).then((_){
print('DB recreated!');
Future.wait([_insertInitialData()]).then((_) {
print('_insertInitialData done');
Future.wait([_insertAdditionalData()]).then((_){
print('_insertAdditionalData done');
});
});
});
} catch (ex) {
print('There was a problem in populateDB(): $ex');
}
}```
Using await makes things a lot easier to read and will block execution of later lines until the action has finished.
Future<void> populateDB() async {
final localDB = LocalDatabase.instance;
await localDB.dropDB(recreateDB: true);
print('DB recreated!');
await _insertInitialData();
print('_insertInitialData done');
await _insertAdditionalData();
print('_insertAdditionalData done');
}
You can try using only one future statement, and follows it with multiple "then". This makes sure the first "then" will be completed before the second "then" is executed. I assume your localDB.dropDB(recreateDB: true) function is asynchronous.
Future<void> _insertAdditionalData() async{}
void populateDB() {
try {
final localDB = LocalDatabase.instance;
localDB.dropDB(recreateDB: true).then((_){
print('DB recreated!');
}).then((_) {
_insertInitialData();
print('_insertInitialData done');
}).then(() {
_insertAdditionalData();
print('_insertAdditionalData done');
});
} catch (ex) {
print('There was a problem in populateDB(): $ex');
}
}
Cool. Thanks for your comments. I replaced all of those Future.wait for async/await even in my internal methods that insert into the DB and it's all good!!! (executing in the sequence I need)
Just learning Dart/Flutter for fun and I love it.

Is there a way to get notified when a dart stream gets its first result?

I currently have an async function that does the following:
Initializes the stream
Call stream.listen() and provide a function to listen to the stream.
await for the stream to get its first result.
The following is some pseudo code of my function:
Future<void> initStream() async {
// initialize stream
var stream = getStream();
// listen
stream.listen((result) {
// do some stuff here
});
// await until first result
await stream.first; // gives warning
}
Unfortunately it seems that calling stream.first counts as listening to the stream, and streams are not allowed to be listened by multiple...listeners?
I tried a different approach by using await Future.doWhile()
Something like the following:
bool gotFirstResult = false;
Future<void> initStream() async {
var stream = getStream();
stream.listen((result) {
// do some stuff here
gotFirstResult = true;
});
await Future.doWhile(() => !gotFirstResult);
}
This didn't work for me, and I still don't know why. Future.doWhile() was successfully called, but then the function provided to stream.listen() was never called in this case.
Is there a way to wait for the first result of a stream?
(I'm sorry if I didn't describe my question well enough. I'll definitely add other details if needed.)
Thanks in advance!
One way is converting your stream to broadcast one:
var stream = getStream().asBroadcastStream();
stream.listen((result) {
// do some stuff here
});
await stream.first;
Another way, without creating new stream, is to use Completer. It allows you to return a Future which you can complete (send value) later. Caller will be able to await this Future as usual.
Simple example:
Future<int> getValueAsync() {
var completer = Completer<int>();
Future.delayed(Duration(seconds: 1))
.then((_) {
completer.complete(42);
});
return completer.future;
}
is equivalent of
Future<int> getValueAsync() async {
await Future.delayed(Duration(seconds: 1));
return 42;
}
In your case:
Future<void> initStream() {
var stream = getStream();
var firstValueReceived = Completer<void>();
stream.listen((val) {
if (!firstValueReceived.isCompleted) {
firstValueReceived.complete();
}
// do some stuff here
});
return firstValueReceived.future;
}

Dart Flutter, help me understand futures

See this code:
class SomeClass{
String someVariable;
SomeClass();
Future<String> getData () async {
Response response = await get('http://somewebsite.com/api/content');
Map map = jsonDecode(response.body); // do not worry about statuscode, trying to keep it minimal
someVariable = map['firstName'];
return 'This is the first name : $someVariable';
}
}
Now look at main:
void main(){
String someFunction() async {
SomeClass instance = SomeClass(); // creating object
String firstNameDeclaration = await instance.getData().then((value) => value);
return firstNameDeclaration;
}
}
When working with Future, like in the case of firstNameDeclaration why do I have to use .then() method to access the string object, since I am waiting for the function to finish?
When searching on the web, some people use .then() others don't, I am confused.
Kindly help me have a clearer understanding of how Futures and async functions overall work.
Background
Asynchronous operations let your program complete work while waiting for another operation to finish. Here are some common asynchronous operations:
Fetching data over a network.
Writing to a database.
Reading data from a file.
To perform asynchronous operations in Dart, you can use the Future class and the async and await keywords.
When an async function invokes "await", it is converted into a Future, and placed into the execution queue. When the awaited future is complete, the calling function is marked as ready for execution and it will be resumed at some later point. The important difference is that no Threads need to be paused in this model.
Futures vs async-await
When an async function invokes "await", it is converted into a Future, and placed into the execution queue. When the awaited future is complete, the calling function is marked as ready for execution and it will be resumed at some later point. The important difference is that no Threads need to be paused in this model.
async-await is just a a declarative way to define asynchronous functions and use their results into Future and it provides syntactic sugar that help you write clean code involving Futures.
Consider this dart code snipped involving Futures -
Future<String> getData(int number) {
return Future.delayed(Duration(seconds: 1), () {
return 'this is a future string $number.';
});
}
main(){
getData(10).then((data) => {
print(data)
});
}
As you can see when you use Futures, you can use then callback when the function return a future value. This is easy to manage if there is single "then" callback but the situation escalates quickly as soon as there are many nested "then" callbacks for example -
Future<String> getProductCostForUser() {
return getUser().then((user) => {
var uid = user.id;
return getOrder(uid).then((order) => {
var pid = order.productId;
return getProduct(pid).then((product) => {
return product.totalCost;
});
});
});
}
main(){
getProductCostForUser().then((cost) => {
print(cost);
});
}
As you can when there multiple chained "then" callback the code become very hard to read and manage. This problem is solved by "async-await". Above chained "then" callbacks can be simplified by using "async-await" like so -
Future<String> getProductCostForUser() async {
var user = await getUser();
var order = await getOrder(user.uid);
var product = await getProduct(order.productId);
return product.totalCost;
}
main() async {
var cost = await getProductCostForUser();
print(cost);
}
As you can above code is much more readable and easy to understand when there are chained "then" callbacks.
I hope this explains some basic concepts and understanding regarding the "async-await" and Futures.
You can further read about topic and examples here
Basically, you should either use await OR then(). However, Dart guidelines advocates that you should prefer use await over then() :
This code :
Future<int> countActivePlayers(String teamName) {
return downloadTeam(teamName).then((team) {
if (team == null) return Future.value(0);
return team.roster.then((players) {
return players.where((player) => player.isActive).length;
});
}).catchError((e) {
log.error(e);
return 0;
});
}
should be replaced by :
Future<int> countActivePlayers(String teamName) async {
try {
var team = await downloadTeam(teamName);
if (team == null) return 0;
var players = await team.roster;
return players.where((player) => player.isActive).length;
} catch (e) {
log.error(e);
return 0;
}
}
In your case, you should write :
void main(){
Future<String> someFunction() async {
SomeClass instance = SomeClass(); // creating object
String firstNameDeclaration = await instance.getData();
return firstNameDeclaration;
// Or directly : return await instance.getData();
// Or : return instance.getData();
}
}

How to call async functions in Stream.periodic

Is it possible to call an async function inside dart:Stream.periodic function?
I tried to wrap my async function but it is not working, please see code below.
Stream.periodic(Duration(seconds: _pollingInterval), _checkConnectivity)
String _checkConnectivity(int x) async {
return await _connectionRepository.checkConnection();
}
Use asyncMap:
Stream<String> checkConnectionStream() async* {
yield* Stream.periodic(Duration(seconds: _pollingInterval), (_) {
return _connectionRepository.checkConnection();
}).asyncMap((event) async => await event);
}
I'm not too familiar with dart streams yet, but you should be able to simulate what you're trying to achieve like this:
final controller = StreamController<String>();
Timer timer;
controller.onListen = () {
timer = Timer.periodic(
_pollingInterval,
(timer) => _connectionRepository.checkConnection().then((data){
if(!controller.isClosed){
controller.add(data);
}
}),
);
};
controller.onCancel = () {
timer?.cancel();
}
return controller.stream;
The stream does not support pause and continue, though. If you want that you'd need to override the corresponding callbacks on the controller and start/stop the timer there.
Also, depending on the timing of checkConnection this can result in events in the stream being very different to _pollingInterval.