Компонент Dart: как вернуть результат асинхронного обратного вызова?

Привет, я новичок в Dart Futures, и у меня следующая ситуация.

Каждый раз, когда пользователь вводит букву в пользовательском интерфейсе, вызывается метод addressChanged() в моем ui_component. Этот метод вызывает метод getProposals() в моем компоненте карт, который выполняет асинхронный запрос к API карт Google. Как только будут получены результаты, я хочу вернуть их компоненту пользовательского интерфейса, который заполнит раскрывающийся список свойств в пользовательском интерфейсе.

Я застрял на последнем шаге: как (и как лучше всего) вернуть результаты асинхронной функции обратного вызова родительскому компоненту (при сохранении повторно используемого компонента карт?).

Вот что я пробовал:

1) UI_Component:

// I get called if a user typed a new letter
     Future addressChanged(dynamic event) async {
        String id = event.target.id;
        String address = event.target.value;
          if(id=="pickup") {
              this.pickup = address;
          } else if(id=="destination") {
              this.destination = address;
          }
        // this is where I call the subcomponent and want to get the address propasals
        String proposals = await googleMap.getProposals(address,id);
        print(proposals);
        populateProposalDropdown();
      }

2) Компонент Google Map:

  Future getProposals(String address,String id) async {
    await _getProposals(address,id);
  }

  Future _getProposals(String address,String id) async {

    if(address != "") {
      autocompleteService.getPlacePredictions(
          new AutocompletionRequest()
            ..input = address
          ,
          (predictions,status) {
            List<String> result = [];
            if(status == PlacesServiceStatus.OK) {
              predictions.forEach(
                  (AutocompletePrediction prediction) =>
                      result.add(prediction.description)
              );
            }

            // HERE is the problem: How do I return this result from the callback as a result of the getProposals method?
            return result;
          }
      );
    }
  }

person Blackbam    schedule 14.02.2017    source источник
comment
AutoCompleteService ваш код? Его можно переписать так, чтобы он возвращал сам Future вместо того, чтобы вызывать обратный вызов, что избавило бы вас от необходимости использовать Completer при его вызове.   -  person Argenti Apparatus    schedule 14.02.2017
comment
К сожалению, это не так: pub.dartlang.org/packages/google_maps. Им действительно стоит реализовать такую ​​библиотеку ;-)   -  person Blackbam    schedule 14.02.2017


Ответы (1)


Этот метод не возвращает никаких данных

  Future getProposals(String address,String id) async {
    await _getProposals(address,id);
  }

Измените это на

  Future getProposals(String address,String id) {
    return _getProposals(address,id);
  }

Это тоже сработает, но здесь async и await излишни

  Future getProposals(String address,String id) async {
    return await _getProposals(address,id);
  }

Для _getProposals вы можете использовать Completer

  Future _getProposals(String address,String id) async {
    if(address != "") {
      Completer completer = new Completer();

      autocompleteService.getPlacePredictions(
          new AutocompletionRequest()
            ..input = address
          ,
          (predictions,status) {
            List<String> result = [];
            if(status == PlacesServiceStatus.OK) {
              predictions.forEach(
                  (AutocompletePrediction prediction) =>
                      result.add(prediction.description)
              );
            }

            // HERE is the problem: How do I return this result from the callback as a result of the getProposals method?
            completer.complete(result);
          }
      );
      return completer.future;
    }
    return null;
  }
person Günter Zöchbauer    schedule 14.02.2017
comment
Спасибо, это именно то, что мне нужно :-) - person Blackbam; 14.02.2017
comment
Рад слышать :) - person Günter Zöchbauer; 14.02.2017