Async Futures按顺序运行完成

时间:2013-05-25 20:05:39

标签: dart

我遇到了以下示例(下面的示例1),这让我想知道我是否可以改变我处理Futures的方式并删除所有保留处理顺序的嵌套函数调用,但这会导致缩进我觉得有点乱。

但我的程序的更改版本无效。它没有保留处理顺序,也没有“等待”功能完成。例如,在从第一次调用(fGetUserInput)返回之前,调用了另一个后续函数。

为什么在例1中,顺序处理所有“第一级”“新未来”,但是在例2中,我改变了代码,不保留处理顺序。正在处理对fGetUserInput的调用时,处理其后的一个Futures?

是否“示例1”仅“有效”,因为所有语句都是同步的?

我遇到了对“runAsync”的引用。可以用来实现我想要的吗? (按顺序处理,没有任何缩进)。

    // Example 1. Code that I encountered  for Futures //

import 'dart:async';

main() {

  new Future(() => print('1'))
   .then((_) => print('a'))
   .then((_) => print('b'));

  new Future(() => print('2'))
   .then((_) => print('c'))
   .then((_) => print('d'));

  new Future(() => print('3'))
   .then((_) => 
       new Future(() => print('e'))
       .then((_) => print('f'))
   );

  new Future(() => print('4'))
   .then((_) => 
       new Future(() => print('g'))
       .then((_) => print('d'))
   );
}

以上导致以下控制台输出顺序: -

1   a   b   2   c   d   3   4   e   f   g   d

我认为这是有道理的。

因此,我修改了我的代码以测试它如下: -

   // Example 2. Altered version of my code which //
   // does not preserve the order of processing,  //
   // which is necessary for program to function. //

  new async.Future(() => fGetUserInput())
  .then((lInput) {
    iMaxIters = int.parse(lInput[4]);
    tClearTable = (lInput[5] == "y");

    iDivisor = fInitialize(iMaxIters);

    tgPrint = false;  // printing off

    sUri =
     "postgres://${lInput[1]}:${lInput[2]}@localhost:5432/${lInput[3]}";
    sStartTime = lInput[7];
  })
  .catchError((oError) => fFatal("Get User Input", oError));

  new async.Future(() => fConnectToDb(sUri, sStartTime))
  .then((bool tConnected) {
    if (ogDb == null)
      fFatal("Unable to connect to database", "");
    print ("Processing database ......");
  })
  .catchError((oError) => fFatal("Connect to Db", oError));

  new async.Future(() => fClearTable(tClearTable))
  .then((sResult) => print (sResult+"\n"))
  .catchError((oError) => fFatal("Clear Table", oError)); 

  new async.Future(() => fProcessInserts(iMaxIters, iDivisor))
  .then((sResult) => print (""))
  .catchError((oError) => fFatal("Process Inserts", oError));

  new async.Future(() => fSetupRandKeys())
  .then((sResult) => print (""))
  .catchError((oError) => fFatal("Setup Random Keys", oError));

  new async.Future(() => fProcessUpdates(iMaxIters, iDivisor))
  .then((sResult) {
    String sTotValue = fFormatAmount(igGrandTotAmt, true, 2);
    fPrint ("Grand Total added to database = \$${sTotValue}");
    ogDb.close();
    exit(0);
  })
  .catchError((oError) => fFatal("Process Updates", oError));
}  

void fFatal (String sMessage, Error oError) {
  print("\n\nFatal Error. $sMessage\n${oError}");
  exit(1);
}

async.Future<String> fProcessInserts(int iMaxIters, int iDiv) {
  async.Completer oCompleter = new async.Completer<String>();

  int iTot = 0;
  Function fLoop;

  print ("\nProcessing Inserts ......");
  fResetAndStartWatch();

以下是我在上述更改之前的代码,以下示例3似乎正常工作。我不喜欢缩进的程度,并且在更多函数调用的情况下,这会增加缩进的程度。我希望有一种更优雅的方式去做。

    // Example 3: The original version of my code //
    // which does preserve the order of processing //
void main() {

  print("");

  String sCheckPoint = "Get User Input";
  fGetUserInput()
  .then((lInput) {
    int iMaxIters = int.parse(lInput[4]);
    bool tClearTable = (lInput[5] == "y");

    int iDiv = fInitialize(iMaxIters);

    tgPrint = false;  // printing off

    String sUri =
      "postgres://${lInput[1]}:${lInput[2]}@localhost:5432/${lInput[3]}";

    sCheckPoint = "Connect to Database";
    fConnectToDb(sUri, lInput[7]).then((bool tConnected) {
      if (ogDb == null)
        fFatal(sCheckPoint, "Unable to conenct to Db");
      print ("Processing database ......");
      sCheckPoint = "Clear Table";
      fClearTable(tClearTable).then((sResult) {
        print (sResult+"\n");
        sCheckPoint = "Process Inserts";
        fProcessInserts(iMaxIters, iDiv).then((sResult) {
          print;
          sCheckPoint = "Set-up Random Keys";
          fSetupRandKeys().then((sResult) {
            print;
            sCheckPoint = "Process Updates";
            fProcessUpdates(iMaxIters, iDiv).then((sResult) {
              String sTotValue = fFormatAmount(igGrandTotAmt, true, 2);
              fPrint ("Grand Total added to database = \$${sTotValue}");
              ogDb.close();
              exit(0);
            });
          });
        });
      });
    });
  })
  .catchError((oError) => fFatal(sCheckPoint, oError));
}

void fFatal (String sMessage, Error oError) {
  print("\n\nFatal Error. $sMessage\n${oError}");
  exit(1);
}

async.Future<String> fProcessInserts(int iMaxIters, int iDiv) {
  async.Completer oCompleter = new async.Completer<String>();

  int iTot = 0;
  Function fLoop;

  print ("Processing Inserts ......");
  fResetAndStartWatch();

1 个答案:

答案 0 :(得分:1)

请记住,你可以连接期货,这会减少你的缩进量。

缺点是您没有获得嵌套作用域,如果您有多个值在异步块之间传播,这可能很有用,但这可以通过几种方式解决。

以下是带链接的示例3:

// Example 3 with chaining
void main() {
  String checkPoint = "Get User Input";
  getUserInput().then((input) {
    int maxIters = int.parse(input[4]);
    bool clearTable = (input[5] == "y");

    int div = initialize(maxIters);

    shouldPrint = false;  // printing off

    String uri =
        "postgres://${input[1]}:${input[2]}@localhost:5432/${input[3]}";

    checkPoint = "Connect to Database";
    return connectToDb(uri, input[7]).then((bool connected) {
      if (db == null)
          fatal(checkPoint, "Unable to conenct to Db");
      print ("Processing database ......");
      checkPoint = "Clear Table";
      return clearTable(shouldClearTable);
    }).then((result) {
      print (result+"\n");
      checkPoint = "Process Inserts";
      return processInserts(maxIters, div);
    }).then((result) {
      print('');
      checkPoint = "Set-up Random Keys";
      return setupRandKeys();
    }).then((result) {
      print('');
      checkPoint = "Process Updates";
      return processUpdates(maxIters, div);
    }).then((result) {
      String totValue = formatAmount(grandTotAmt, true, 2);
      print("Grand Total added to database = \$${totValue}");
      return db.close();
      // exit(0); pretty much never call exit()
    });
  }).catchError((error) => fatal(checkPoint, error));
}

编辑:哎呀,仔细观察我对范围问题有所了解......我添加了一个嵌套级别,只是为了捕获以下块可访问的范围内所需的变量。我也删除了匈牙利语符号,因为......不要在Dart中这样做:)