2014-11-09 1 views
2

Привет всемНекоторые пояснения Completer

У меня есть один класс «Пример», которому нужно сделать некоторые вычисления. Я вызываю start(), которые вызывают _next(). Во время вычисления _next() вызывает себя пару раз, но в моем примере я имитирую это с помощью таймера. Вот мой код

import "dart:async"; 


main() { 

    Example ex = new Example(); 

    for (var i = 0 ; i < 3 ; i++) { 
     ex.start().then((nbr) { 
      print(nbr); 
     }); 
    } 

} 

class Example { 

    /// for _next 
    Completer _insideCompleter; 

    /// from start() to outside 
    Completer _outsideCompleter; 

    Example(); 

    /// start is just a better public api than next when we start the exercise 
    Future<int> start() { 

     _insideCompleter = new Completer(); 
     _outsideCompleter = new Completer(); 


     _next().then((int value) { 
      print("value: $value"); 
      _outsideCompleter.complete(value); 

     }).catchError((message) { 
      print("information: $message"); 
     }); 

     return _outsideCompleter.future; 
    } 


    /// _next handle the flow with the status 
    Future<int> _next() { 

     new Timer(new Duration(seconds: 6),() { 
      _insideCompleter.complete(15); 
     }); 

     return _insideCompleter.future; 
    } 
} 

она заканчивается: плохое состояние: Будущее уже завершено. но как вы можете видеть в начале(). Завершение воссоздается с новым. Поэтому я не понимаю, почему он уже завершен.

Если кто-нибудь может объяснить, почему это не правильно закодировать так, и, возможно, дать мне некоторые интересные ссылки, было бы здорово

Ура!

ответ

1

Я не совсем уверен, что ваше намерение с кодом, но я думаю, вы должны либо

Example ex = new Example(); 

for (var i = 0 ; i < 3 ; i++) { // create a new Example() for each iteration here 
    ex.start().then((nbr) {  // or ensure that the next iteration is not executed 
     print(nbr);    // before the previous is completed. 
    }); 
} 

с этим кодом ex.start() называются 3 раза до того, как первый вызов завершен.

+0

Hummm да я думаю, я получил его ... Я выполняю 3 раза start() _insideCompleter создается 3 раза, но каждый раз на одной и той же ссылке, что означает, что в конце есть только один экземпляр, который заканчивается в первый раз ... я прав? – BenNG

+0

Yup, вот как это работает. Вы хотите, чтобы 'start' вызывался (почти) одновременно или должен был быть отложен следующий вызов до тех пор, пока предыдущий не был закончен? Вы можете использовать 'Future.doWhile()' для достижения этого. –

+0

Я подумаю об этом на самом деле ... Я застрял ... Я никогда не использую Future.doWhile() Повод увидеть, как это работает :) – BenNG

1

Здесь главный вопрос о завершивших называемых в функции обратного вызова

_next().then((int value) { 
      print("value: $value"); 
      _outsideCompleter.complete(value); // this line 

     }) 

и

new Timer(new Duration(seconds: 6),() { 
      _insideCompleter.complete(15); // this line 
     }); 

Поскольку это 2 функции называется после цикла и вашего завершившима является атрибутом, все обратные вызовы будут использовать последние _outsideCompleter и _insideCompleter.

Таким образом, после чем один из обратного вызова есть «потреблять» ваш завершающего, другие будут создавать исключение «плохое состояние: Будущее уже завершено»

здесь версия, которая работает

import "dart:async"; 


main() { 

    Example ex = new Example(); 

    for (var i = 0 ; i < 3 ; i++) { 
    ex.start().then((nbr) { 
     print(nbr); 
    }); 
    } 

} 

class Example { 

    Example(); 

    /// start is just a better public api than next when we start the exercise 
    Future<int> start() { 

    var outsideCompleter = new Completer(); // create localy each times 


    _next().then((int value) { 
     print("value: $value"); 
     outsideCompleter.complete(value); 

    }).catchError((message) { 
     print("information: $message"); 
    }); 

    return outsideCompleter.future; 
    } 


    /// _next handle the flow with the status 
    Future<int> _next() { 
    var insideCompleter = new Completer(); // create localy each times 

    new Timer(new Duration(seconds: 6),() { 
     insideCompleter.complete(15); 
    }); 

    return insideCompleter.future; 
    } 
}