Дарт / Флаттер дозирования forEach () л oop? - PullRequest
0 голосов
/ 11 февраля 2020

У меня есть следующий код для вызова API, чтобы получить мои данные, а затем проанализировать результаты. Насколько я понимаю, «asyn c» на forEach l oop НЕ блокирует, поэтому я использую входной bool для установки, хочу ли я, чтобы они блокировали вызовы или нет.

Моя проблема сейчас заключается в том, что в некоторых моих вызовах возникает ошибка «сокет: слишком много открытых файлов», предположительно, потому что я достиг предела во флаттере для слишком многих вещей, ожидающих HTTP-ответов API (дайте мне знать, если вам нужна дополнительная информация из функций "TX")

Так что мой вопрос заключается в следующем. Есть ли быстрый способ задушить неблокирующее «forEach» l oop ниже и, возможно, сделать ожидание на будущее. Задержка (Длительность (миллисекунды: 250)), скажем, для каждого 5-го раза через l oop?

Конечно, если я просто посчитаю и жду asyn c вызова в приведенном ниже коде, я думаю, что forEach l oop будет продолжать проходить через все остальное.

Нужно ли составлять временный список всех записей и делать их в неблокирующих партиях?

    if (makeBlocking) {
      for (var r in _commissionData[gwSerial].rooms.entries) {
        Map<String, dynamic> res = await _getSetupRoomDevicesApi.tx(
            _token, _clientId, gwSerialString, r.value.id);
        Map<String, dynamic> res2 = await _listCommissionAssociations.tx(
            _token, _clientId, gwSerialString, r.value.id);
        processCommissionData(r.value, res, res2);
      }
    } else {
      if (_commissionData != null) {
        _commissionData[gwSerial]?.rooms?.forEach((roomId, r) async {
          Map<String, dynamic> res = await _getSetupRoomDevicesApi.tx(
              _token, _clientId, gwSerialString, r.id);
          Map<String, dynamic> res2 = await _listCommissionAssociations.tx(
              _token, _clientId, gwSerialString, r.id);
          processCommissionData(r, res, res2);
        });
      }
    }

1 Ответ

0 голосов
/ 11 февраля 2020

Хорошо, вот что я в итоге сделал. Я создал небольшую функцию, которую можно ожидать, если блокировать, или нет, если не блокировать. Тогда просто используйте простой для l oop.

Проблема, с которой я сталкивался, заключалась в переборе карты и, естественно, с использованием forEach, она не блокировала ее. Но я хотел добавить паузу (то есть газ) так часто в этой неблокирующей l oop. Но это означало бы использование для l oop, но я не мог сделать для l oop body "asyn c".

Может быть, я пока не делаю это "лучшим" способом, поэтому обратная связь приветствуется:

  Future<void> syncGatewayRoomDeviceDetailData(
      int gwSerial, bool makeBlocking) async {
    if (_clientId == 0) {
      setState(() {
        _lastCommissionRoomUpdate = DateTime.now();
      });
    } else {
      if (DateTime.now().difference(_lastCommissionRoomUpdate).inMilliseconds >
          -1) {
        print("Sync Gateway:$gwSerial blocking:$makeBlocking");
        _lastCommissionRoomUpdate = DateTime.now();
        String gwSerialString =
            gwSerial.toRadixString(16).padLeft(8, '0').toUpperCase();

        if (makeBlocking) {
          for (var r in _commissionData[gwSerial].rooms.entries) {
            await getAndProcessCommissionData(r, gwSerialString);
          }
        } else {
          // Even if not blocking, still need to throttle
          var throttleCount = 0;
          for (var r in _commissionData[gwSerial].rooms.entries) {
            if (++throttleCount % 9 == 0) {
              await Future.delayed(Duration(milliseconds: 500));
            }
            getAndProcessCommissionData(r, gwSerialString);
          }
        }
      } else {
        print("sync delayed: $gwSerial ");
      }
    }
  }

  Future<void> getAndProcessCommissionData(var r, String gwSerialString) async {
    Map<String, dynamic> res = await _getSetupRoomDevicesApi.tx(
        _token, _clientId, gwSerialString, r.value.id);
    Map<String, dynamic> res2 = await _listCommissionAssociations.tx(
        _token, _clientId, gwSerialString, r.value.id);
    processCommissionData(r.value, res, res2);
  }
...