如何在dart中同步来自异步函数的调用

时间:2019-12-20 00:20:07

标签: flutter dart firebase-cloud-messaging

伙计们,我正在Flutter上开发我的第一个应用程序,我对Java和js有一定的经验,但是我之前从未使用过flutter,所以对不起,如果我的问题对您来说太可笑了。

该应用是语音助手聊天机器人,应该对客户收到的每条新消息执行文本到语音的转换,我的问题是,由于我使用的是Firebase消息传递,因此我收到的所有请求都在异步调用中,但是我需要将对文本的访问同步到语音服务,否则我会遇到一个文本中断另一个文本的问题。

这是我目前的代码: Firebase消息传递:

onMessage: (Map<String, dynamic> message) {
        return this.handleBotMessage(appState, message);
},

描述如何处理每条特定消息的方法:

Future handleBotMessage(
    Store<AppState> store,
    Map<String, dynamic> dataJson,
  ) {
      #logic that convert the message into json and extracts the message type

      if (type == MessageType.CHAT_MESSAGE) {
        return handleChatMessage(store, subtype, messageMap);
      }
  }

处理短信的方法:

Future<dynamic> handleChatMessage(
    Store<AppState> store,
    MessageSubtype subtype,
    Map<String, dynamic> message,
  ) {
    #Text to speach is build as a singleton and this always returns the same instance
    TextToSpeech tts = TextToSpeech();
    if (subtype == MessageSubtype.TEXT) {
      TextMessage textMessage = TextMessage.fromJson(message);
      return tts
          .speak(textMessage.text)
          .then((result) => store.dispatch(NewBotMessageAction(textMessage)));
    } else if (subtype == MessageSubtype.QUICK_REPLY) {
      QuickReplyMessage qrMessage = QuickReplyMessage.fromJson(message);
      return tts
          .speak(qrMessage.text)
          .then((result) => store.dispatch(NewQrOptionsAction(qrMessage)));
    } else {
      throw new Exception('Unexpected message subtype!');
    }
  }

实际执行文本转语音的方法

Future<dynamic> speak(String text) async {
    return flutterTts.speak(text).then((resp) {
      ttsRunning = false;
      print(resp);
      return resp;
    }, onError: (obj, st) {
      ttsRunning = false;
      print(obj);
      print(st.toString());
    });
  }

文本到语音的初始化

Future init() async {
    await flutterTts.setLanguage("en-US");
    var res = await flutterTts.isLanguageAvailable("en-US");
    print(res);
    return res;
  }

https://pub.dev/packages/flutter_tts

2 个答案:

答案 0 :(得分:1)

如果您不希望新消息打扰正在说的人,则可以将它们排队。这样,新消息将等待当前消息完成。看看这种方法:

Queue of Future in dart

答案 1 :(得分:0)

好吧,我找到了解决方案,问题就象frank06指出的那样,颤抖的tts可以立即完成未来,而不是在说完整个短语之后。
所以这是我的解决方案,虽然不是完美的方法,但是可以解决问题:

Completer completer;
Future<dynamic> speak(String text) {
    print('Started speeking');
    print(new DateTime.now().toIso8601String());
    if (TextToSpeech.lastRequest == null) {
      lastRequest = _executeSpeech(text);
    } else {
      lastRequest = lastRequest.then((resp) {
        return _executeSpeech(text);
      });
    }
    return lastRequest;
  }

  Future<dynamic> _executeSpeech(String text) {
    completer = Completer();
    flutterTts.speak(text).then((resp) {
      ttsRunning = false;
      print(resp);
      return resp;
    }, onError: (obj, st) {
      ttsRunning = false;
      print(obj);
      print(st.toString());
    });
    return completer.future;
  }


flutterTts.setCompletionHandler(() {
  print('Finished speeking');
  print(new DateTime.now().toIso8601String());
  ttsState = TtsState.stopped;
  completer.complete(ttsState);
});

flutterTts.setErrorHandler((msg) {
  ttsState = TtsState.stopped;
  completer.complete(ttsState);
});