【问题标题】:How should I use an async future list in another async function?我应该如何在另一个异步函数中使用异步未来列表?
【发布时间】:2020-10-04 06:27:41
【问题描述】:

我正在尝试使用异步方法从网站获取 url 列表。 在获得 url 列表后,我尝试在另一个异步方法中使用 url。

这里是用来获取网址的:

void _getData() async {
    final response =
        await http.get('https://www.whateverurl');
    print(response.statusCode);
    dom.Document document = parser.parse(response.body);
    final elements2 = document.getElementsByClassName('image-card-wrapper');
    setState(() {
      //fetches links as /tiger /catalina etc.
      urlList = elements2.map((element) async {
        url = 'https://www.whateverurl' +
            element.getElementsByTagName('a')[0].attributes['href'];
        print(element.getElementsByTagName('a')[0].attributes['href']);
        return url;
      }).toList();
        await _tryFetch(urlList);
    });
  }

成功了。我可以得到清单。我无法解决的是:我试图在另一个异步函数中使用这个 url 列表来获取每个项目的具体技术信息。

 _tryFetch(List urls) async {
    String e = '';
    for (var item in urls) {
      try {
        final response2 = await http.get(item);
        dom.Document document2 = parser.parse(response2.body);
        final elements = document2.getElementsByClassName('sqs-block-content');
        elements.forEach((element) {
          if (element.getElementsByTagName('li').isNotEmpty) {
            List a = element.getElementsByTagName('li');
            print(a.length);
            for (var i = 0; i < a.length; i++) {
              var z = a[i].children[0].text ?? '...';
              e = e + z.toString();
            }
          }
          setState(() {
            tekniskInfo.add(e);
            print(tekniskInfo);
          });
        });
      } on Exception catch (_) {
        print('elele');
      }
    }
  }
@override
  void initState() {
    _getData();
    super.initState();
  }

在我的 Scaffold 中,当尝试在 ListView.builder 中使用此 teksniskInfo[index] 时; 它抛出错误:Future String is not sub of String...

我尝试添加一个按钮来使用 _tryFetch() 函数。当我按下按钮时它起作用。但问题是,当我第一次导航到该页面时,它会抛出我提到的错误。

总结;如何在另一个未来函数中使用未来列表?

【问题讨论】:

  • 尝试将 await 添加到 urlList。等待 _tryFetch(等待 urlList);或者只是删除 elements2.map 中的异步

标签: flutter asynchronous dart


【解决方案1】:

前言

  1. async 和 await 关键字支持异步编程,让您编写看起来与同步代码相似的异步代码。

  2. 标记为async 的每个函数都返回Future

所以在另一个异步函数中使用异步函数(返回Future)的方式是await函数的结果

Future<String> foo() => ...;

Future<void> bar() {
  final String = await foo();
}

...
await bar(); //somewhere else    
...

回到你的代码

我在_getData() 中看到错误 - 你不能使 setState(fn) 的函数参数异步,所以接下来是错误代码

setState(() { 
  await foo(); //Error! - you can't await Future in synchronous function
});

您可以通过在异步结果后调用 setState 来缓解这种情况

void _getData() async {
  ...
  await _tryFetch();
  ...
  setState((){});
}

现在你需要等待列表中的每个 Future(最后一个等待)

List<Future<String>> urlList = elements2.map((element) async {...

_tryFetch(List urls) async {
  String e = '';
  for (var item in urls) {
    try {
      final response2 = await http.get(await item); //each is Future<String> you need to wait

但是没有必要把async匿名函数放到map(...)中

结果将是List&lt;String&gt; urlList = elements2.map((element) {...,无需等待每个列表项

欢迎在 cmets 中与我联系

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多