Flutter中从Node.js Socket获取坐标数据并返回值问题:改造函数后返回null
解决Socket异步数据返回null的问题
我明白你遇到的困扰了——你的函数之所以返回null,是因为Socket的回调事件是异步触发的,而你的函数在回调还没执行、geocoordinateObject还没被赋值的时候,就已经执行到return语句了。
要解决这个问题,我们可以用Dart里的Completer来等待Socket回调中的数据,让函数的Future在数据准备好之后再完成。下面是具体的改造方案:
核心思路
Completer可以帮我们手动控制Future的完成时机:
- 创建一个
Completer<GeocoordinateModel?>实例 - 在Socket的
geocoordinateData回调中,当拿到有效数据时调用completer.complete(geocoordinateObject) - 如果遇到连接失败、超时或无有效数据的情况,调用
completer.complete(null)或completer.completeError() - 最后返回
completer.future,让函数的Future等待数据就绪后再返回结果
修改后的完整代码
import 'dart:async'; // 引入Completer所需的库 import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:real_chat/data/model/geocoordinate_model.dart'; import 'package:socket_io_client/socket_io_client.dart' as IO; import 'package:socket_io_client/socket_io_client.dart'; class GeocoordinateApi { static const String url = 'https://xxx.herokuapp.com/'; Future<GeocoordinateModel?> getCoordinate() async{ // 创建Completer实例,用来控制Future的完成时机 final completer = Completer<GeocoordinateModel?>(); IO.Socket socket = IO.io(url, OptionBuilder().setTransports(['websocket']).build()); socket.on("connect", (data) { socket.on('geocoordinateData', (message) { if (message != null && message['payload'] != null) { final geocoordinateMap = Map<String,dynamic>.from(message['payload']); final geocoordinateObject = GeocoordinateModel.fromMap(geocoordinateMap); print(geocoordinateObject); // 数据就绪,完成Completer并返回结果 completer.complete(geocoordinateObject); // 拿到数据后主动断开socket,避免资源浪费 socket.disconnect(); } else { // 无有效数据时返回null completer.complete(null); socket.disconnect(); } }); }); // 处理socket连接失败的情况 socket.on("connect_error", (error) { print('Socket连接失败: $error'); completer.complete(null); }); // 处理socket连接超时 socket.on("connect_timeout", (_) { print('Socket连接超时'); completer.complete(null); }); // 返回Completer的Future,等待数据就绪 return completer.future; } }
关键修改点说明
- 导入
dart:async:必须导入这个库才能使用Completer类 - 添加
Completer实例:它相当于一个异步触发器,只有调用complete()方法时,对应的Future才会返回结果 - 回调中完成Completer:当
geocoordinateData事件触发并解析出有效数据后,调用completer.complete(geocoordinateObject),此时函数的Future才会返回目标对象 - 错误边界处理:添加了连接失败、超时的监听,避免Completer一直处于等待状态(防止内存泄漏)
- 主动断开连接:拿到数据后及时断开Socket,减少不必要的资源占用
这样改造后,你的函数就会等待Socket返回数据后再返回结果,不会再提前返回null了。
内容的提问来源于stack exchange,提问作者gbeto Jean-José
相关产品推荐
相关产品推荐

