2013-05-08 36 views
2

有人會讚賞以下一些幫助。我正在編寫一些控制檯測試程序,我希望能夠從終端輸入一些參數(我不想使用命令行參數 - 參數太多)。我嘗試了一些變化,但我無法找到如何實現這一點。以下是我的終端輸入測試的最新版本。這個程序的問題是,如果遇到錯誤,Completer自動關閉,我想從Main()或者fGetNumber()函數繼續。雖然我可以看到爲什麼這個程序不起作用,但它說明了我需要實現的功能 - 重新輸入數字,但我無法找到如何實現這一點。如果輸入了有效的號碼,則沒有問題。如果輸入了無效號碼,我無法找到如何重新輸入號碼。async.Future async.Completer - 如果出現錯誤,如何「繼續」

的代碼如下,我的問題是由 「//////////」 強調:

import "dart:async" as async; 
import "dart:io"; 

void main() { 
    fGetNumber("Enter Nr of Iterations : ", 0, 999999) 
    .then((int iIters){ 
    print ("In Main : Iterations selected = ${iIters}"); 
    if (iIters == null) { 
     print ("In Main: Invalid Number of iterations : ${iIters}."); 
    } else { 
     fProcessData(iIters); 
    } 
    print ("Main Completed");  
    }); 
} 

async.Future<int> fGetNumber(String sPrompt, int iMin, int iMax) { 
    print ("In fGetNumber"); 
    int iIters = 0; 
    async.Completer<int> oCompleter = new async.Completer(); 

    while (!oCompleter.isCompleted) { /////////// This loop does not work /////// 
    return fGetUserInput(sPrompt).then((String sIters) { 
     iIters = int.parse(sIters); 
     if (iIters < iMin || iIters > iMax) throw new Exception("Invalid");   
     oCompleter.complete(iIters); 
     return oCompleter.future; 
    }).catchError((_) => print ("Invalid - number must be from ${iMin} to ${iMax}") 
    ).whenComplete(() => print ("fGetNumber - whenComplete"));// always gets here 
    } 
    print ("In fGetNumber (at end of function)");  //// it never gets here 
} 

async.Future<String> fGetUserInput(String sPrompt) { 
    print ("In fGetUserInput"); 
    async.Completer<String> oCompleter = new async.Completer(); 

    stdout.write(sPrompt); 
    async.Stream<String> oStream = stdin.transform(new StringDecoder()); 
    async.StreamSubscription oSub; 
    oSub = oStream.listen((String sData) { 
    oCompleter.complete("$sData"); 
    oSub.cancel(); 
    }); 

    return oCompleter.future; 
} 

void fProcessData(int iIters) { 
    print ("In fProcessData"); 
    for (int iPos = 1; iPos <= iIters; iPos++) { 
    if (iPos%100 == 0) print ("Processed = ${iPos}"); 
    } 
    print ("In fProcessData - completed ${iIters}"); 
} 

回答

3

//這個循環不工作

當然它確實 - 你只輸入一次,你立即返回,因此離開循環和方法。

//總是能夠在這裏

這是因爲whenComplete()總是被調用,成功或錯誤。

//它從來沒有在這裏

得到因爲你已經返回該方法的。

那麼可以做些什麼?

最簡單的方法是不依賴於fGetUserInput()。聽stdinfGetNumber,只完成了完成者/取消訂閱如果輸入的是有效的:

async.Future<int> fGetNumber(String sPrompt, int iMin, int iMax) { 

    print ("In fGetNumber"); 
    async.Completer<String> oCompleter = new async.Completer(); 

    stdout.write(sPrompt); 
    async.Stream<String> oStream = stdin.transform(new StringDecoder()); 
    async.StreamSubscription oSub; 
    oSub = oStream.listen((String sData) { 
    try { 
     int iIters = int.parse(sData); 
     if (iIters < iMin || iIters > iMax) throw new Exception("Invalid"); 
     oCompleter.complete(iIters); 
     oSub.cancel(); 
    } catch(e) { 
     print("Invalid - number must be from ${iMin} to ${iMax}"); 
     stdout.write(sPrompt); 
    } 
    }); 

    return oCompleter.future; 
} 

有沒有辦法?

當然。有可能有很多種方法來做到這一點。這一個例子:

async.Future<int> fGetNumber(String sPrompt, int iMin, int iMax) { 
    print ("In fGetNumber"); 
    async.Completer<int> oCompleter = new async.Completer(); 
    fGetUserInput(sPrompt, oCompleter, (String sIters) { 
    try { 
     int iIters = int.parse(sIters); 
     if (iIters < iMin || iIters > iMax) throw new Exception("Invalid"); 
     return iIters; 
    } catch(e) { 
     print ("Invalid - number must be from ${iMin} to ${iMax}"); 
     stdout.write(sPrompt); 
    } 
    return null; 
    }); 
    return oCompleter.future; 
} 

void fGetUserInput(String sPrompt, async.Completer oCompleter, dynamic inputValidator(String sData)) { 
    print ("In fGetUserInput"); 
    stdout.write(sPrompt); 
    async.Stream<String> oStream = stdin.transform(new StringDecoder()); 
    async.StreamSubscription oSub; 
    oSub = oStream.listen((String sData) { 
    var d = inputValidator(sData); 
    if(d != null) { 
     oCompleter.complete(d); 
     oSub.cancel(); 
    } 
    }); 
} 

如果你真的覺得應該有一些由鏢隊解決,你可以寫一個feature request。但是Completer只能完成一次。無論你寫什麼代碼,你都不能一次又一次地循環完成它。

+0

感謝您的回覆。然而,我確實已經知道,我想要一個「標準」輸入函數和其他「調用」該函數的函數 - 例如。字符串,整數,貨幣等。但是,如果您發佈的是實現「it」的唯一方式,我會接受答案,但是,我認爲「this」需要通過「Dart」解決。但是,也許我錯了。異步恕我直言,需要發佈爲「等待」,或其他東西來解決這種情況。 – 2013-05-08 11:40:25

+0

@BrianOh我說「最簡單」,而不是「唯一的」。我正在編輯答案以顯示另一種方法。可能有更多的選擇。 – MarioP 2013-05-08 11:56:35

+0

也許禁用Completer自動完成的能力將是一個「解決方案」。然後「我的」循環會起作用(?)。如果有自動完成功能,爲什麼需要「完整」?我可能過度簡化了「問題」,或者至少我認爲是一個問題。 – 2013-05-08 13:35:24

相關問題