Как вернуть будущее из будущего? Или это запрещено в асинхронной библиотеке?

Как я могу вернуть значение Future из объекта Future? Этот код не работает.

import 'dart:async';

    void main() {
      var temp = foo();
      temp.then((Future<int> future) {
        future.then((int result) {
          print(result);
        });
      });
    }

    Future<Future<int>> foo() {
      return new Future<Future<int>>(() {
        return new Future<int>(() => 5);
      });
    }

Как предотвратить ненужное разворачивание?

В этом случае в асинхронной библиотеке Future объявлен общий класс.

abstract class Future<T> {
}

Если я создам выражение следующим образом

new Future<Future<int>>();

Затем с типом T, указанным как Future<int>, какой результат ожидается от универсального класса Future?

Я считаю, что результат должен быть таким, как указано в аргументе типа T.

I.e. Future<int>.

Но результат не такой, как ожидалось. Информации об этом ненормальном поведении на сайте Dart API нет.

Если это «функция» (но я думаю, что ненормальное поведение неправильно называть «функцией»), то почему она не задокументирована в Dart API?

Чем можно объяснить это несоответствие?

Почему этот код не выдает ошибок и предупреждений?

Другой ИДЕНТИЧНЫЙ пример, но без использования Future.

void main() {
  var temp = foo();
  temp.baz((Foo<int> foo) {
    foo.baz((int result) {
      print(result);
    });
  });
}

Foo<Foo<int>> foo() {
  return new Foo<Foo<int>>(() {
    return new Foo<int>(() => 5);
  });
}

Если в этом случае результат будет таким же, как при использовании Future (т.е. неожиданным), то как мы можем назвать этот код? Нормальный или ненормальный?

А может Будущее в Дротике какое-то особенное (волшебное)?


person mezoni    schedule 05.06.2013    source источник


Ответы (2)


Посмотрите документацию api http://api.dartlang.org/docs/releases/latest/dart_async/Future.html

Там сказано:

If the returned value is itself a Future, completion of the created future will wait until
the returned future completes, and will then complete with the same result.

Думаю, это означает, что вы не можете вернуть будущее из будущего. Но вы можете вернуть список фьючерсов.

void main() {
  var temp = foo();
  temp.then((List<Future<int>> list) {
    list[0].then((int result) {
      print(result);
    });
  });
}

Future<List<Future<int>>> foo() {
  return new Future<List<Future<int>>>(() {
    return [new Future<int>(() => 5)];
  });
}
person SpiderPig    schedule 05.06.2013

Нет необходимости в дополнительной упаковке. Согласно документации Future:

Если возвращаемое значение само является [Future], завершение созданного future будет ждать завершения возвращенного future, а затем завершится с тем же результатом.

Это означает, что вы можете переписать свой код как:

import 'dart:async';

void main() {
  var temp = foo();
  temp.then((int result) {
    print(result);        
  });
}

Future<int> foo() {
  return new Future<int>(() {
    return new Future<int>(() => 5);
  });
}

Это намного проще в работе и обеспечивает ожидаемый результат.

person Pixel Elephant    schedule 05.06.2013
comment
Возвращение реального будущего ‹T› быстро сделало бы невозможным использование фьючерсов в сложных кодовых базах. Вложение нескольких Futures сделало бы код нечитаемым и трудным для работы. Я очень рад, что команда Dart реализовала Futures таким образом. Любые опасения по поводу несоответствия стандартной обработке дженериков решаются явным примечанием в документации о том, как должны обрабатываться возвращенные Futures. - person Pixel Elephant; 05.06.2013
comment
programmers.stackexchange.com - подходящее место для теоретических дискуссий. - person Zdeslav Vojkovic; 05.06.2013