您如何调用一个 future,然后将该 return 值传递给另一个 future 到 运行?

How do you call one future and then pass that return value into another future to run?

我正在尝试用我的 Android 相机拍照,将照片上传到 Google Firebase 存储,在存储中获取该图像的可下载 URL,然后更新用户在 Firestore 上的照片 Feed。如果我只调用 takeImage() 它会获取图像并成功上传到存储。如果我使用虚拟图像 url 调用 _uploadImage,它会正确更新提要。但是我无法将 takeImage 的结果作为参数传递给 _uploadImage()。

void takeAndSave() async {
              url = await takeImage();
              _uploadImage(url);


          }


Future<String> takeImage() async {
    // open camera
    var image = await ImagePicker.pickImage(source: ImageSource.camera);

    // save image to temp storage
    final String fileName = "${Random().nextInt(10000)}.jpg";

    Directory directory = await getApplicationDocumentsDirectory(); // AppData folder path
    String appDocPath = directory.path;



    // copy image to path
    File savedImage = await image.copy('$appDocPath/' + fileName);

    // upload file to Firebase Storage
    final StorageReference ref = FirebaseStorage.instance.ref().child(fileName);
    final StorageUploadTask task = ref.putFile(savedImage);
    String downloadURL = await ref.getDownloadURL();
    url = downloadURL;
    //    _image = image;

    return downloadURL;
}



Future<void> _uploadImage(String url) async {
    final FirebaseUser user = await widget.auth.currentUser();
    String uid = user.uid;
    print('uid = ' + uid);
    print(url);
      // upload URL to Firebase Firestore Cloud Storage

      Firestore.instance.runTransaction((Transaction transaction) async {
        DocumentReference _newPhoto = Firestore.instance.collection('users').document(user.uid);

        await _newPhoto.collection('cards').add({"url" : url});

      });
  }

根据您的代码,它应该可以正常工作,但您的 takeImage() 方法可能会返回异常。尝试捕获该异常并查看是否有帮助。

以下引用自https://www.dartlang.org/tutorials/language/futures#async-await

如果返回 Future 的函数完成时出现错误,您可能希望捕获该错误。异步函数可以使用 try-catch 处理错误:

Future<String> takeImage() async {
  try {
    // Your code
  } catch (e) {
    // Handle error...
  }
}

链接未来的任务: 意味着如果我们有两个未来的任务,第二个依赖于第一个响应的结果,那么我们可以使用“Future.wait()”。在下面的示例中,我创建了两个带有 async 关键字的方法,它们将从服务器获取数据,我想在第一个 "fetchPost()" 的响应之后执行 "fetchPostAgain()" 方法,然后我可以使用 "Future.wait()".

import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_app/models/Post.dart';
import 'package:http/http.dart' as http;

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
  }

  FetchFirstPost getFirstPost;
  String myString = "Loading...";

  void _takeImage() {
    Future.wait([fetchPost()]).then((FutureOr) => {
        fetchPostAgain()
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Example'),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              SingleChildScrollView(
                child: Text(myString),
              ),

              RaisedButton(
                    child: Text("Run Future"),
                    onPressed: _takeImage,
                          ),
              ],
          ),
          /*child: CallApiDemo(),*/
        ),
      ),
    );
  }



  Future<Post> fetchPost() async {
    final Completer completer = Completer();
    final response = await http.get('https://jsonplaceholder.typicode.com/posts/1');
    log('data: ' + response .statusCode.toString());
    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON
      setState(() {
        myString = response.body;
      });
      return postFromJson(response.body);
    } else {
      // If that call was not successful, throw an error.
      throw Exception('Failed to load post');
    }
  }

  Future<Post> fetchPostAgain() async{
    final response = await http.get('https://jsonplaceholder.typicode.com/posts/1');
    log('GOT SECOND RESPONSE');
    log('data: ' + response .statusCode.toString());
    if (response.statusCode == 200) {
      setState(() {
        myString = myString + "\n\n\nAGAIN\n\n\n" + response.body;
      });
      return postFromJson(response.body);
    } else {
      // If that call was not successful, throw an error.
      throw Exception('Failed to load post');
    }
  }

}