Flutter Futures:如何使该 StompClient 连接可通过 Futures 等待?

问题描述 投票:0回答:2

我正在使用 StompClient 连接到我的游戏服务器 Websocket 端点。为了使用 Flutter 的

FutureBuilder
,我希望此客户端具有异步/等待功能。

因此我通过以下方式包装了StompClient:

class CombatClient {
  late StompClient _client;

  Future<bool> connect() async {
    _client = StompClient(
      config: StompConfig.SockJS(
        url: '${ServerGlobals.backendHost}/connect',
        onConnect: (frame) async {
          _client.subscribe(destination: "/gameserver/foo", callback: (data) => {print("foo: ${data.body}")});
        },
      ),
    );
    _client.activate();
    return await Future.doWhile(() => _client.connected);
  }
}

在我的主要逻辑中,我使用这样的整体:

final combatClient = CombatClient();
await combatClient.connect();

但是由于以下错误,这不起作用:

E/flutter (23147): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'FutureOr<bool>'
E/flutter (23147): #0      CombatClient.connect (package:app/combat/websocket/combat_client.dart:19:12)
E/flutter (23147): <asynchronous suspension>
E/flutter (23147): #1      _DebugCombatPageState.build.<anonymous closure> (package:app/debug/debug_combat_page.dart:61:27)
E/flutter (23147): <asynchronous suspension>
E/flutter (23147):

无论错误如何,我只是想知道正确的方法是什么。当涉及到期货等时,我总是很挣扎。我找不到正确的 API 用法来连接到游戏服务器awaitable

flutter future flutter-futurebuilder
2个回答
1
投票

引自@pskink

简单地使用 Completer 类而不是 return wait Future.doWhile(... - 文档说:“一种生成 Future 对象并稍后用值或错误完成它们的方法”


0
投票
import 'dart:async';
import 'package:flutter/material.dart';

import 'package:stomp_dart_client/stomp.dart';
import 'package:stomp_dart_client/stomp_frame.dart';
import 'package:stomp_dart_client/stomp_config.dart';

extension FutureHelper<T> on Future<T> {
  static Future<void> doWhileByDuration(FutureOr<bool> Function() action, {Duration duration = Durations.extralong4}) => Future.doWhile(() => Future.sync(action).then((isDone) => isDone ? Future.delayed(duration, () => true) : Future.value(false)));
}

class CombatClient {
  late StompClient _client;

  Future<void> connect() {
    _client = StompClient(
      config: StompConfig.SockJS(
        url: '${ServerGlobals.backendHost}/connect',
        onConnect: (frame) async {
          _client.subscribe(destination: "/gameserver/foo", callback: (data) => {print("foo: ${data.body}")});
        },
      ),
    );
    _client.activate();
    return FutureHelper.doWhileByDuration(() => !_client.connected, duration: Durations.long2);
  }
}

或者:

import 'dart:async';
import 'package:flutter/material.dart';

import 'package:stomp_dart_client/stomp.dart';
import 'package:stomp_dart_client/stomp_frame.dart';
import 'package:stomp_dart_client/stomp_config.dart';

class CombatClient {
  final Completer _completer = Completer<bool>();
  late StompClient _client;

  Future<bool> connect() async {
    _client = StompClient(
      config: StompConfig.SockJS(
        url: '${ServerGlobals.backendHost}/connect',
        onStompError: (frame) {
          _completer.complete(false);
        },
        onConnect: (frame) async {
          _client.subscribe(destination: "/gameserver/foo", callback: (data) => {print("foo: ${data.body}")});
          _completer.complete(true);
        },
      ),
    );
    _client.activate();
    return _completer.future;
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.