Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to periodically call a function only if it has finished executing the previous time in Dart?

I'm making a Flutter app where I need to periodically call a funtion every 5 seconds. Here is my current implementation:

Timer.periodic(markerRefreshInterval, (Timer t) {
    print('$markerRefreshInterval seconds over, refreshing...');
    _fetchMarkersFromDb(); // updates markers every 5 seconds
});

However, sometimes (due to network issues, etc.) the _fetchMarkersFromDb() function takes longer than 5 seconds to execute. In such cases, I've figured out (with the help of debug prints in the console) that there are multiple instances (threads?) of the same function being executed parallely. This messes up a variable I'm trying to increment in each function call.

I want _fetchMarkersFromDb() to be called at a minimum interval of 5 seconds, or the total function execution time + 5 seconds (if the function itself takes long to execute). I do not want it to run parallely like it does now. I've heard that Streams can be used, but I'm confused as to how to use them while calling the function repeatedly in an interval.

Full source code can be found here, and the issue I'm trying to solve is here. Thanks in advance.

like image 302
Urmil Shroff Avatar asked Dec 05 '25 03:12

Urmil Shroff


1 Answers

You can use package https://pub.dev/packages/neat_periodic_task
It has the following features

  • Run a periodic task on a loop.
  • Limit maximum run-time to prevent a hanging loop.
  • Retry failed task executions after a timeout.
  • Catch and log all exceptions/errors from the task.
  • (Optionally) prevent concurrent tasks using status in a storage service that supports optimistic concurrency (eg. Cloud Datastore, Google Cloud Storage).
  • Print log messages liveness monitoring of the periodic tasks.

example code snippet

import 'dart:io';
import 'package:neat_periodic_task/neat_periodic_task.dart';

void main() async {

  final scheduler = NeatPeriodicTaskScheduler(
    interval: Duration(seconds: 5),
    name: 'hello-world',
    timeout: Duration(seconds: 5),
    task: () async => print('Hello World'),
    minCycle: Duration(seconds: 5),
  );

  scheduler.start();
  await ProcessSignal.sigterm.watch().first;
  await scheduler.stop();
}
like image 171
chunhunghan Avatar answered Dec 07 '25 19:12

chunhunghan