Будущая последовательность

В следующем коде я думал, что f1 > f2 > f3 будет порядком вызова, но вызывается только f1. Как я могу заставить 3 функции вызываться последовательно?

Я добавил следующее в функцию main, и она работает, как и ожидалось, но я хочу знать, есть ли другие окончательные способы достижения тех же результатов?

print('Starting main');
List<Future> futures=new List<Future>();
Future v1=f1();
Future v2=f2();
Future v3=f3();
futures.add(v1);
futures.add(v2);
futures.add(v3);
Future.wait(futures);
print('Leaving main');

import 'dart:async';

Duration d1 = new Duration(seconds: 5);
Duration d2 = new Duration(seconds: 10);
Duration d3 = new Duration(seconds: 15);

bool r1 = false;
bool r2 = false;
bool r3 = false;

void cb1() {
    print('Entering CB1');
    r1 = true;
    print('Leaving CB1');
}

void cb2() {
    print('Entering CB2');
    r2 = true;
    print('Leaving CB2');
}

void cb3() {
    print('Entering CB3');
    r3 = true;
    print('Leaving CB3');
}

Timer t1;
Timer t2;
Timer t3;

Future<bool> start1() {
    print('Entering start1');
    Completer<bool> r = new Completer();
    r.future.then((_) {
        while (!r1) {

        }
        print('Completing start1');
        r.complete(true);
    });

    print('Leaving start1');
    return r.future;
}

Future<bool> start2() {
    print('Entering start2');
    Completer<bool> r = new Completer();
    r.future.then((_) {
        while (!r2) {

        }
        print('Completing start2');
        r.complete(true);
    });

    print('Leaving start2');
    return r.future;
}

Future<bool> start3() {
    print('Entering start3');
    Completer<bool> r = new Completer();
    r.future.then((_) {
        while (!r3) {

        }
        print('Completing start3');
        r.complete(true);
    });

    print('Leaving start3');
    return r.future;
}

Future<bool> f1() {
    print('Entering f1');
    Completer<bool> result = new Completer();
    t1 = new Timer(d1, cb1);
    result.complete(start1());

    print('Leaving f1');
    return result.future;
}

Future<bool> f2() {
    print('Entering f2');
    Completer<bool> result = new Completer();
    t2 = new Timer(d2, cb2);
    result.complete(start2());

    print('Leaving f2');
    return result.future;
}

Future<bool> f3() {
    print('Entering f3');
    Completer<bool> result = new Completer();
    t3 = new Timer(d3, cb3);
    result.complete(start3());

    print('Leaving f3');
    return result.future;
}

void main() {
    print('Starting main');
    f1().then((_) {
        f2().then((_) {
            f3().then((_) {

            });
        });
    });
    print('Leaving main');
}

person signtheta    schedule 14.12.2014    source источник
comment
Ваши startX методы кажутся очень странными. Какова их цель? Циклическое ожидание переменной до тех пор, пока она не получит определенное значение, является очень плохим стилем. Вы должны использовать события обратных вызовов, но никогда с пустым циклом.   -  person Günter Zöchbauer    schedule 14.12.2014
comment
привет, это всего лишь тестовый код, чтобы понять, как работает будущий механизм. я изо всех сил пытаюсь понять концепцию будущего в дротиках.. я думаю, что понимаю ваш очищенный товарищ по коду... но свяжусь с вами.... большое спасибо, приятель!   -  person signtheta    schedule 14.12.2014
comment
Рекомендуемое чтение dartlang.org/articles/event-loop, dartlang.org/docs/tutorials/futures   -  person Günter Zöchbauer    schedule 14.12.2014
comment
Если у вас есть конкретный вопрос, просто вернитесь к SO!   -  person Robert    schedule 15.12.2014
comment
как бы вы написали код для вызова асинхронной функции в синхронизированной функции и ожидания возврата асинхронной функции?   -  person signtheta    schedule 17.12.2014


Ответы (2)


В первую очередь следует уточнить, зачем вам это нужно. Я действительно не понимаю, почему вы хотите, чтобы они выполнялись последовательно - вы должны дать нам больше информации о концепции, стоящей за этим.

Пожалуйста, дайте нам больше информации о том, чего вы хотите достичь! Следующий код каким-то образом делает то, что, как я думаю, вы хотите:

// Я еще немного почистил код:

import 'dart:async';

Duration d1 = new Duration(seconds: 5);
Duration d2 = new Duration(seconds: 10);
Duration d3 = new Duration(seconds: 15);

Future<bool> f1() {
  print('Entering f1');
  Completer<bool> r = new Completer();
  new Timer(d1, () {
    r.complete(true);
  });
  print('Leaving f1');
  return r.future;
}

Future<bool> f2() {
  print('Entering f2');
  Completer<bool> r = new Completer();
  new Timer(d2, () {
    r.complete(true);
  });
  print('Leaving f2');
  return r.future;
}

Future<bool> f3() {
  print('Entering f3');
  Completer<bool> r = new Completer();
  new Timer(d3, () {
    r.complete(true);
  });
  print('Leaving f3');
  return r.future;
}

void main() {
    print('Starting main');
    f1().then((_) {
        f2().then((_) {
            f3().then((_) {

            });
        });
    });
    print('Leaving main');
}
person Robert    schedule 14.12.2014
comment
привет Роб, как я уже упоминал в своем комментарии выше, это всего лишь тестовый код, чтобы «увидеть», как работает будущий механизм. ваш код был полезен, но я не думаю, что у меня есть концепция под моим поясом :( все еще ищу подробный учебник по этому вопросу. спасибо за вашу помощь, приятель! очень ценю!! - person signtheta; 14.12.2014
comment
Неважно, слушаете ли вы будущее до или после его завершения, слушатель все равно получит результат в более поздней микрозадаче. - person lrn; 15.12.2014

В start1 вы возвращаете будущее, которое никогда не завершается. В основном, что вы делаете, это:

start1() {
  var r = new Completer();
  r.then.((_) { ... r.complete() ... });
  return r.future;
}

Поскольку единственное завершение r требует завершения r, этого не произойдет. Это означает, что result из f1 будет вечно ждать будущего, возвращаемого start1, а f1().then((_) ... никогда не доберется до обратного вызова then. Вот почему ничего не происходит.

У вас также есть цикл ожидания-занятости while (!r1) {}. Если вы намерены зависнуть, если r1 не соответствует действительности, тогда все работает нормально. Фьючерсы не выполняются одновременно в Dart. Вы должны вернуться в цикл событий до того, как будет вызван какой-либо будущий обратный вызов, поэтому, если r1 будет ложным при достижении цикла, он останется ложным, потому что никакой другой код никогда не прервет цикл.

Если я понимаю, что вы хотите с start1, возможно, попробуйте переписать его на:

// Returns a future which completes when `r1` becomes true.
start1() {
  var r = new Completer();
  void check() {
    if (r1) {
      r.complete();
    } else {
      // We can't use scheduleMicrotask here, because an infinite microtask
      // loop would prevent the timer from firing.
      Timer.run(check);  // Check again later.
    }
  }
  check();
  return r.future;
}
person lrn    schedule 15.12.2014
comment
Irn, отличное объяснение и большое спасибо за это! как насчет того, чтобы сделать хороший учебник для абсолютных новичков, приятель? ;) - person signtheta; 16.12.2014