代码之家  ›  专栏  ›  技术社区  ›  Stéphane de Luca

如何在Dart中等待异步下载完成或出错?

  •  0
  • Stéphane de Luca  · 技术社区  · 4 年前

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

      /// 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');
        }
    
      }
    
    1 回复  |  直到 4 年前
        1
  •  1
  •   jamesdlin    4 年前

    你的 startDownloading 函数在注册回调以侦听 Stream 流动

    流动 要完成,您可以保存 StreamSubscription 退回 .listen 然后 await 这个 Future 从…起 StreamSubscription.asFuture

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