【问题标题】:Flutter Await Callback Not Give Any ResponseFlutter Await 回调不给出任何响应
【发布时间】:2019-02-16 17:20:14
【问题描述】:

我仍然是 dart Flutter 的初学者,现在我正在尝试从 REST API 和 socket.IO 检索数据。这时候我有一个困惑的问题,我已经尝试在互联网上搜索3天,但没有解决方案。我有 async 和 await 脚本,但是我添加的函数 await 没有给出任何响应并且仍然暂停。

假设我有两个不同的文件,第一个是主文件,第二个是辅助文件。

ma​​in.dart

Future<List<ChatTile>> fetchChat(socketutil,id) async {

  socketutil.join(id); //STACK IN HERE
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String messagePrefs = prefs.getString('messagePrefs');
  print("DUA");
  return await compute(parseListChat, messagePrefs);
}

helper.dart

Future<void> join(String id_room) async {
      String jsonData ='{"room_id" : "$id_room","user_id" : "5a91687811138e74009839c9","user_name" : "Denis Muhammad Ramdan","user_photo" : "photo.jpg","user_status" : "1"}';
      socketIO.sendMessage("join", jsonData, null);
      //subscribe event
      return await socketIO.subscribe("updateMessageList", (result) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        await prefs.setString('messagePrefs', result);
        print('SATU');
        return await result;
      });
  }

我的问题是我的代码有问题,最好的方法是什么?

非常感谢,

【问题讨论】:

  • 看起来您希望 return await result;join(...) 返回,但实际上并非如此。它只是从您传递给subscribe(...) 的回调中返回。我不知道 socketIO 到底是什么或 socketIO.subscribe() 返回什么,但订阅听起来像返回的 Future 可能只会在连接关闭时返回,这可能永远不会,这就是为什么 compute() 永远不会完成。
  • 感谢@Günter Zöchbauer 的回答,我已经尝试添加await behind socketutil.join (id); 就像这样等待socketutil.join (id); 但代码仍然暂停并且不会继续下一次执行。处理这种情况的最佳方法是什么?
  • 正如我所说,我不知道socketIO.subscribe() 返回什么,所以很难提出建议。我的假设是 socketIO.subscribe() 永远不会完成,所以等待对您没有帮助。

标签: dart async-await flutter


【解决方案1】:

我建议您将await_only_futures 添加到您的分析仪配置中

analysis_options.yaml

lint:
  rules:
   - await_only_futures

你也不需要return await something,因为你的函数已经返回了一个未来,这是多余的。

从我看到的 socketio subscribe 方法来看,它不会像您期望的那样返回结果,而是使用回调并且不会返回它 (https://pub.dartlang.org/documentation/flutter_socket_io/latest/flutter_socket_io/SocketIO/subscribe.html)

要处理这个问题,你应该使用Completer

final completer = Completer<String>()

socketIO.subscribe("updateMessageList", (result) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString('messagePrefs', result);
    socketIO.unSubscribe("updateMessageList");
    completer.complete(result);
  });

return completer.future;

你可能想在使用completer.completeError(error)时处理错误

更新

您也可以将订阅转换为 Dart Stream 以处理更多情况。

StreamController<String> controller;

Stream<String> get onUpdateMessageList {
   if (controller != null) return controller.stream;

   constroller = StreamController<String>.broadcast(
     onCancel: () => socketIO.unSubscribe("updateMessageList"),
   );

   socketIO.subscribe("updateMessageList", constroller.add);

   return controller.stream;
}



Future<StreamSubscription> join(String id_room) async {
  ...
  return onUpdateMessageList.listen((result) async {
   SharedPreferences prefs = await SharedPreferences.getInstance();
   await prefs.setString('messagePrefs', result);
  });
}

【讨论】:

  • 传递给subscribe的回调是否只调用了一次?如果它被多次调用,那么我认为也应该在某处调用取消订阅。
  • 确实,如果你只想要一个结果,你必须取消订阅事件,我会更新
  • @Günter Zöchbauer 和@Hadrien Lejard subscribe 可以多次调用。
  • @DenisRamdan 在您的fetchChat 函数中,您是想在每次有updateMessageList 时更新共享首选项,还是只更新一次然后执行其余函数?
  • 我更新了我的例子,希望我给了你所有可以帮助你的块(Completer、Future、Stream)
猜你喜欢
  • 2021-06-03
  • 2012-06-04
  • 1970-01-01
  • 2020-07-03
  • 2020-03-10
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
相关资源
最近更新 更多