如何等待 Dart 中异步下载的完成或错误?

How to await for the completion or error of an async download in Dart?

我想编写一个线性的多阶段流程(如下所示),从文件下载开始,并有进度:

  /// Processes the database, from download to prices processing.
  Future<void> updateDatabase() async {
    //final fontText = await File('./example/cosmic.flf').readAsString();
    //print(art.renderFiglet('updateDatabase'));

    // == 1) download
    print('1 ======== DOWNLOADING ==========');
    try {
      await startDownloading();
    } catch (err) {}

    // == 2) Decompress: Whatever download was ok or not, we decompress the last downloaded zip file we have locally
    print('2 ======== DECOMPRESSING ========');
    try {
      await startDecompressing();
    } catch (err) {}

    // == i) Stage i, etc.

但是在我的下载阶段有些东西不起作用,因为它开始阶段 2) 前期阶段 1) 完成。

我的第一阶段(下载)是这样的:

  /// Starts download procress
  Future<void> startDownloading() async {
    print("startDownloading…");

    _state = DownloadState.downloading;
    _progress = 0;
    notifyListeners();

    /// Database string url
    final databaseUrlForInstantData = "https://XXX";

    try {
      final request = Request('GET', Uri.parse(databaseUrlForInstantData));

      final StreamedResponse response = await Client().send(request);

      final contentLength = response.contentLength;

      // == Start from zero
      _progress = 0;
      notifyListeners();

      /// The currently downloaded file as an array of bytes
      List<int> bytes = [];

      response.stream.listen(
        /// = Closure listener for newly downloaded bytes
        (List<int> newBytes) {
          bytes.addAll(newBytes);

          final downloadedLength = bytes.length;

          if (contentLength == null) {
            _progress = 0;
          } else {
            _progress = downloadedLength / contentLength;
          }
          notifyListeners();

          print(
              'Download in progress $_progress%: ${bytes.length} bytes so far');
        },

        /// = Download successfully completed
        onDone: () async {
          _state = DownloadState.downloaded;
         
          notifyListeners();

          /// The resulting local copy of the database
          final file = await _getDownloadedZipFile();

          // == Write to file
          await file.writeAsBytes(bytes);
          print('Download complete: ${bytes.length} bytes');
        },

        /// = Download error
        onError: (e) {
          _state = DownloadState.error;
          _error = e.message;
          print('Download error at $_progress%: $e');
        },
        cancelOnError: true,
      );
    }
    // == Catches potential error
    catch (e) {
      _state = DownloadState.error;
      _error = 'Could not download the databse: $e';
      print('Download error at $_progress%: $e');
    }

  }

您的 startDownloading 函数 returns 在注册回调以侦听 Stream 并且不等待 Stream 完成后。

要等待 Stream 完成,您可以保存 .listen 返回的 StreamSubscription,然后 await 来自 [=20] 的 Future =]:

var streamSubscription = response.stream.listen(...);
await streamSubscription.asFuture();