2

一些有关以下内容的帮助将不胜感激。我正在编写一些控制台测试程序,我希望能够从终端输入一些参数(我不想使用命令行参数 - 参数太多)。我尝试了一些变化,但我找不到如何实现这一点。以下是我对终端输入的测试的最新版本。这个程序的问题是,如果遇到错误,完成程序会自动关闭,我想从 Main() 或 fGetNumber() 函数继续。虽然我可以看到为什么该程序不起作用,但它说明了我需要实现的目标 - 重新输入数字,但我找不到如何实现。如果输入有效数字,则没有问题。如果输入了无效号码,我不知道如何重新输入号码。

代码如下,我遇到的问题用“//////////”突出显示:

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}");
} 
4

1 回答 1

4

// 这个循环不起作用

当然可以——你只输入一次,然后立即返回,因此离开循环和方法。

// 总是到这里

那是因为whenComplete()总是被调用,成功或错误。

// 它永远不会到达这里

因为你已经退出了方法。

那么可以做些什么呢?

最简单的方法是不依赖fGetUserInput(). stdin如果输入有效,则监听fGetNumber并仅完成完成者/取消订阅:

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();
    }
  });
}

如果你真的觉得 Dart 团队应该解决一些问题,你可以写一个功能请求。但它Completer被设计为只完成一次。无论您编写什么代码,您都不能一次又一次地循环完成它。

于 2013-05-08T11:31:28.983 回答