首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何按调用顺序运行多个异步函数(FIFO?)

如何按调用顺序运行多个异步函数(FIFO?)
EN

Stack Overflow用户
提问于 2019-04-08 22:17:57
回答 2查看 1.6K关注 0票数 4

我花了好几个小时寻找解决办法,但由于我是省道乞丐,我一个人找不到答案。我想要实现的是,在应用程序运行时,为一些随机调用的异步函数(比方说,当用户在我的应用程序中点击一个按钮时)从代码中的不同点创建类似的队列。我希望按照调用的顺序执行它们,因此基本上我有异步方法,如、updateDate()、和,当用户点击X按钮时,updateDate()将被调用(添加到队列),类似于Y和updatePoints()。当用户按一下(例如X、X、Y)时,我想按这样的顺序运行updateDate()、updateDate()、updatePoints()。当一项任务完成后,另一项任务就开始了。我想我不能用等待来实现这一点。任何提示都将不胜感激!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-09 05:21:54

代码语言:javascript
复制
import 'dart:async';
import 'dart:collection';
import 'dart:math';

Future<void> main() async {
  _simulateRealWork();
}

Scheduler _scheduler = Scheduler();

class Scheduler {
  bool _scheduled = false;

  Queue<Future Function()> _queue = Queue<Future Function()>();

  void schedule(Future Function() task) {
    _queue.add(task);
    if (!_scheduled) {
      _scheduled = true;
      Timer(Duration(seconds: 0), _execute);
    }
  }

  Future _execute() async {
    while (true) {
      if (_queue.isEmpty) {
        _scheduled = false;
        return;
      }

      var first = _queue.removeFirst();
      await first();
    }
  }
}

void _simulateRealWork() {
  var maxPeriod = 5;
  var count = 5;
  for (var i = 0; i < count; i++) {
    print('Timer $i');
    var random = Random();
    Timer(Duration(seconds: random.nextInt(maxPeriod)), () {
      print('Scheduled work $i');
      Future work() async {
        print('Started work $i');
        await Future.delayed(Duration(seconds: random.nextInt(maxPeriod)));
        print('Ended work $i');
      }

      _scheduler.schedule(work);
    });
  }
}

结果:

Timer 0 Timer 1 Timer 2 Timer 3 Timer 4 Scheduled work 2 Started work 2 Scheduled work 0 Scheduled work 3 Ended work 2 Started work 0 Scheduled work 1 Scheduled work 4 Ended work 0 Started work 3 Ended work 3 Started work 1 Ended work 1 Started work 4 Ended work 4

票数 4
EN

Stack Overflow用户

发布于 2019-04-09 06:02:01

在大型任务队列中使用以下代码可能是一种糟糕的做法,但如果您确信任务数组不会超过足够的大小--这可能工作得很好:

代码语言:javascript
复制
Future<List<T>> runOneByOne<T>(List<T Function()> list) {
  if (list.isEmpty) {
    return Future.value(null);
  }
  Future task = Future<T>.microtask(list.first);
  final List<T> results = [];

  for (var i = 1; i < list.length; i++) {
    final func = list[i];
    task = task.then((res) { results.add(res); return Future<T>.microtask(func); });
  }

  return task.then((res) { results.add(res); return results; });
}

它通过将一个Future封装到另一个one中,一个接一个地执行原来的顺序。results数组用于存储返回的值,最后返回所有值。

如果遇到错误,执行将停止并抛出。结果数组在这种情况下丢失。您可以将try {...}闭包添加到每个microtask包装器中,以忽略错误并在该特定任务中返回null,从而保留results数组中的其他值。

用法示例:

代码语言:javascript
复制
runOneByOne<int>([
  () { print("First"); return 1; },
  () { print("Second"); return 2; },
  () { print("Third"); return 3; },
]).then((results) {
  print(results); // List<int> [ 1, 2, 3 ]
});
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55582540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档