首页 > 解决方案 > 是否可以一次调用多个 API

问题描述

我在颤振中集成了一些 API,但我被卡住了。在 API 的某一时刻,我需要传递过去 15 天的数据,所以在此基础上我得到了一个结果。问题是现在加载时间太长了,因为我使用 for 循环并调用一个 API,然后是第二个 API,然后是第三个,依此类推。我正在寻找的是我可以一起调用我的 15 个 API 吗?

我的代码

  getAllEvent() async {
    final storage = new FlutterSecureStorage();

    String asset_id = await storage.read(key: "asset_id");

    var toDate = DateTime.now();
    var fromDate = toDate.subtract(Duration(days: 1));
    for (var i = 0; i <= 15; i++) {
      // put them into a string
      final fromDateString =
          '${fromDate.year}-${fromDate.month}-${fromDate.day}';
      final toDateString = '${toDate.year}-${toDate.month}-${toDate.day}';
      final f = new DateFormat('yyyy-MM-dd');
      fromDate = fromDate.subtract(Duration(days: 1));
      toDate = toDate.subtract(Duration(days: 1));

      final url =
          'https://apihide/${asset_id}?start=${f.format(fromDate)}&end=${f.format(toDate)}';
      // //print(url);
      // //print(ApiToken);
      http.Response res = await http.get(
        url,
        headers: <String, String>{'x-access-token': ApiToken},
      );
      var data = json.decode(res.body.toString());
      if (data['count'] > 0) {
        eventList.eventListData.addAll(data['items']);
      }
    }

    setState(() {
      eventDataLoaded = true;
      checkDataLoaded();
    });
  }

您可以在代码中看到 for 循环 API 正在一一调用。我需要一次调用它 15 次。(如果我一次点击 15 次,API 没有问题,因为 API 提供者说要这样做。)

标签: flutterdart

解决方案


您需要结合以前的两个答案;那些有太多的硬编码和重复的代码。

这是我的解决方案,看看它是否适合你:

getAllEvent() async {
    final storage = new FlutterSecureStorage();
    
    //Store your Future responses here
    var responses=<Future<http.Response>>[];

    String asset_id = await storage.read(key: "asset_id");

    var toDate = DateTime.now();
    var fromDate = toDate.subtract(Duration(days: 1));
    
  for (var i = 0; i <= 15; i++) {
      // put them into a string
      final fromDateString =
          '${fromDate.year}-${fromDate.month}-${fromDate.day}';
      final toDateString = '${toDate.year}-${toDate.month}-${toDate.day}';
      final f = new DateFormat('yyyy-MM-dd');
      fromDate = fromDate.subtract(Duration(days: 1));
      toDate = toDate.subtract(Duration(days: 1));

      final url =
          'https://apihide/${asset_id}?start=${f.format(fromDate)}&end=${f.format(toDate)}';
      // //print(url);
      // //print(ApiToken);

      // This is where a future will be added to the list. Notice there is no await keyword here, so you are not waiting for the response
      responses.add(http.get(
        url,
        headers: <String, String>{'x-access-token': ApiToken},
      ));
    }
    
    var results=await Future.wait(responses);
    
    for (var res in results) {
      var data = json.decode(res.body.toString());
      if (data['count'] > 0) {
        eventList.eventListData.addAll(data['items']);
      }
    }
    

    setState(() {
      eventDataLoaded = true;
      checkDataLoaded();
    });
  }

请注意,这可以进一步优化。上面代码中的问题是您正在等待所有 API 完成,然后才处理所有 API。假设您不关心结果在 eventListData 中出现的顺序,您可能会在调用到达时对其进行处理。像这样(仅显示从 http.get 调用到 setState() 调用的代码:

      responses.add(http.get(
        url,
        headers: <String, String>{'x-access-token': ApiToken},
      ).then( (res) {
        var data = json.decode(res.body.toString());
        if (data['count'] > 0) {
          eventList.eventListData.addAll(data['items']);
        }
      }));
  
  // closing the for loop here
  }
    
    // you still need to wait the futures to complete before calling setState()
    var results=await Future.wait(responses);
    
//     for (var res in results) {
//       var data = json.decode(res.body.toString());
//       if (data['count'] > 0) {
//         eventList.eventListData.addAll(data['items']);
//       }
//     }

setState(() {
...

当我在这里时:如果您确实关心将响应添加到 eventListData 的顺序怎么办?在这种情况下——你只需要在 then() 中调用 json.decode——毕竟这是你想要尽快运行的慢速部分。你可以这样做:

      
//note that here your responses will have parsed response data
responses.add(http.get(
        url,
        headers: <String, String>{'x-access-token': ApiToken},
      ).then( (res) => json.decode(res.body.toString()));
  
  // closing the for loop here
  }
    
    // you still need to wait the futures to complete before calling setState()
    var results=await Future.wait(responses);
    
     for (var data in results) {
//       no need for this line - already done in then()
//       var data = json.decode(res.body.toString());
       if (data['count'] > 0) {
         eventList.eventListData.addAll(data['items']);
       }
     }

setState(() {
...


推荐阅读