Return 在 Dart 中按照队列中的执行顺序同步异步调用 Futures

Return synchronously called Futures asynchronously in order of execution in queue in Dart

void main() async {
  Future<void> asyncFunction(time, value) async {
    return await Future.delayed(Duration(seconds: time), () => print(value));
  }

  print('1');
  asyncFunction(2, "A");
  asyncFunction(1, "B");
  asyncFunction(0, "C");
  print('2');
}

根据上面的代码,我试图让代码打印为:

1
2
A
B
C

我想同步执行所有函数并将 asyncFunctions (Futures) 发送到某种队列,然后按接收到的顺序执行这些函数。每个函数必须等待前一个函数完成它的 Future,然后它自己执行。

我一直在尝试使用流,但没有做对。

这个有用吗?

void main() async {
  Future<void> asyncFunction(time, value) async {
    return await Future.delayed(Duration(seconds: time), () => print(value));
  }

  print('1');
  print('2');
  await asyncFunction(2, "A");
  await asyncFunction(1, "B");
  await asyncFunction(0, "C");
}

好的,我想出了一些基本的东西:

import 'dart:async';
import 'dart:collection';
import 'dart:math';

var streamController = StreamController<String>();
Queue queue = Queue();
bool busy = false;

Future<void> asyncFunction(value) async {
  await Future.delayed(Duration(seconds: Random().nextInt(4)));
  return print(value);
}

void main() async {
  streamController.stream.listen((letter) async {
    queue.add(letter);
    if (!busy) {
      busy = true;
      while (busy) {
        await asyncFunction(queue.first);
        queue.removeFirst();
        if (queue.isEmpty) {
          busy = false;
        }
      }
    }
  });

  print("1");
  streamController.add("A");
  streamController.add("B");
  streamController.add("C");
  streamController.add("D");
  print("2");
  streamController.add("E");
  streamController.add("F");
  streamController.add("G");
  streamController.add("H");
  print("3");
  print("-");
}

给出期望的结果:

1
2
3
-
A
B
C
D
E
F
G
H

无法使 Future.delayed(2, ...)Future.delayed(1, ...) 之前完成。时间不是这样运作的。相反,您可以做的是依赖 return 值而不是副作用,然后您可以构建 FutureList 并使用 Future.wait 来收集结果并按原始顺序打印它们:

void main() async {
  Future<dynamic> asyncFunction(time, value) async {
    await Future.delayed(Duration(seconds: time));
    return value;
  }

  var futures = <Future<dynamic>>[];
  
  print('1');
  futures.add(asyncFunction(2, "A"));
  futures.add(asyncFunction(1, "B"));
  futures.add(asyncFunction(0, "C"));
  print('2');
  
  var results = await Future.wait(futures);
  for (var result in results) {
    print(result);
  }
}

上述方法的好处是允许多个异步操作可能 运行 并行。

或者,您可以延迟构建 Future.delayed(...) 对象,这样每个对象都不会创建,直到前一个对象完成:

void main() async {
  Future<void> asyncFunction(time, value) async {
    await Future.delayed(Duration(seconds: time), () => print(value));
  }

  var queue = <Future<void> Function()>[];
  
  print('1');
  queue.add(() => asyncFunction(2, "A"));
  queue.add(() => asyncFunction(1, "B"));
  queue.add(() => asyncFunction(0, "C"));
  print('2');
  
  for (var thunk in queue) {
    await thunk();
  }
}

如果你想要一个异步任务队列,其中每个新添加的任务都会延迟到前一个任务完成,你可以自己写一个。

class AsyncQueue<T> {
  Future<T?> _current = Future.value(null);
  Future<T> add(FutureOr<T> Function() task) {
    FutureOr<T> wrapper(void _) => task();
    return _current = _current.then(wrapper, onError: wrapper);
  }
}

您可以将其用作:

Future<void> asyncFunction(time, value) async {
  await Future.delayed(Duration(seconds: time), () => print(value));
}
...
  var queue = AsyncQueue<void>();
  print("1");
  var f1 = queue.add(() => asyncFunction(2, "A"));
  var f2 = queue.add(() => asyncFunction(1, "B"));
  var f3 = queue.add(() => asyncFunction(0, "C"));
  print("2");
  await f3;