2013-05-25 2 views
1

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

Измененная версия моей программы не работает. Он не сохранил порядок обработки и не «дождался» завершения функции. Например, перед возвратом с первого вызова (fGetUserInput) была вызвана другая последующая функция.

Почему в примере 1 все «новое будущее» «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

Помните, что вы можете связать фьючерсы, что значительно уменьшит ваш отступ.

Недостатком является то, что вы не получаете вложенных областей, что может быть полезно, если у вас есть более одного значения для распространения между блоками асинхронного использования, но это можно обойти несколькими способами.

Вот ты пример 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)); 
} 

Edit: К сожалению, присмотревшись я немного проблемой обзорной ... Я добавил уровень вложенности просто захватить необходимый ВАР в рамках доступный по следующим блокам. Я также удаляю венгерско-иш-нотацию, потому что ... не делай этого в Дарте :)

+0

Спасибо, я попробую. Однако не знаю об обозначениях. Я отчитаю. –

Смежные вопросы