首页 > 解决方案 > 如何正确构建此 Dart 异步代码?

问题描述

我还在学习 Dart 和 OOP 并且不能完全正确地做到这一点。问题是由于查询的延迟,_batch.addAll()执行之前_invDetails是从内部 ForEach 填充的。我该如何正确地构建它?

Future<Response> exportAccpac() async {
    final Map<String, dynamic> _inv = {'inv': []};
    final Map<String, dynamic> _invDetails = {'invDet': []};
    final Map<String, dynamic> _batch = {};

    final _qExpenses = Query<UserCompany>(context);
    _qExpenses.where((e) => e.company.id).equalTo(companyId);
    _qExpenses
        .join(object: (e) => e.user)
        .join(set: (u) => u.expense)
        .where((d) => d.date)
        .lessThanEqualTo(date);

    final _expenseList = await _qExpenses.fetch();

    _expenseList.forEach((e) {
      _inv['inv'].add(
        {
         // a bunch of stuff here using e
        },
      );

      e.user.expense.forEach((userExpense) async {

        final _qGlCode = Query<GlCode>(context)
          ..where((g) => g.user_type.id).equalTo(_userTypeId)
          ..where((g) => g.company.id).equalTo(companyId)
          ..where((g) => g.expense_type.id).equalTo(userExpense.expense_type.id);

        final _glCodes = await _qGlCode.fetch();

        _invDetails['invDet'].add({
        // a bunch of stuff here using glCodes
        });
      });
    });

    _batch..addAll(_inv)..addAll(_invDetails);
  }

标签: dart

解决方案


一般避免使用forEach- 尤其是与async. 重构代码如下:

  for (var userExpense in e.user.expense) {
    final _qGlCode = Query<GlCode>(context)
      ..where((g) => g.user_type.id).equalTo(_userTypeId)
      ..where((g) => g.company.id).equalTo(companyId)
      ..where((g) => g.expense_type.id).equalTo(userExpense.expense_type.id);

    final _glCodes = await _qGlCode.fetch();

    _invDetails['invDet'].add({
    // a bunch of stuff here using glCodes
    });
  }

这具有串行执行 GL 代码查询的效果,而以前您是并行启动它们,但没有办法等待它们每次完成。(要做到这一点,你会使用Future.wait,但这里不应该需要它。)

forEach您也可以用 a替换外部for


推荐阅读