Dart uses Future objects whenever there might be a delay in the execution of the code,
say reading the contents of a File or launching a Process. Running chaining Futures such that they run one after the other requires returning a future from within the Future:
Future<X> f1 = action1();
f1 = f1.then((x) => action2());
The key here is the re-assignment of f1 to the result of the then call.
To chain an arbitrarily long list of Futures, you can setup the code like this:
typedef Future MkFuture(v);
List<MkFuture> futureMakers = ...;
Future f1 = null;
for (var f in futureMakers) {
if (f1 == null) {
f1 = f();
} else {
f1 = f1.then((v) => f(v));
}
}
If you have one Future that passes along an object that itself contains a Future, then the same kind of code can work. A good example is the dart:io package Process.start() call. It returns a Future of a Process that is running. Inside the then statement, while working on the Process object, you can call exitCode to get a Future that contain the exit code of the invoked statement. This makes it difficult to easily wait on the process to actually finish.
import 'dart:io';
Future<int> exitCode = Process.start(execName, arguments).then((process) {
// Perform actions such as listening or interacting on the process streams
// return the chained function so that the outside caller can wait on the
// process to end
return process.exitCode;
});
Another option is to use the built-in Future chaning. This can work like this:
This will assign the "f" to the returned future from the "then".