4

これに関する多くの投稿や記事 (async と Futures) を読みましたが、現在の状況がどうなっているのかわかりません。私は多くの異なるバリエーションを試みました。

次のコードを順番に処理しようとしています:

import 'dart:async' as async;
import 'dart:io';
import 'dart:math';
import 'package:postgresql/postgresql.dart' as pg;

var uri = 'postgres://admin:admin@localhost:5432/testdb';
List lgNames = ['Peter', 'Robert', 'Mary', 'Marg', 'William',
           'Vern', 'Dermot', 'Monty', 'Peggy', 'Sue', 'William'];

List lgUsed = [];

Random rand1 = new Random();

void main() {
  pg.connect(uri).then((oDb) {
   print ("Connected to database");

    fClearTable(oDb).then((String sResult){
      print(sResult);      

      for (int iPos = 0; iPos < 3; iPos++) {   
        fListTable(oDb, "Select before Insert number ${iPos+1}").then((String sResult) =>
          print(sResult));  

        fInsertData(oDb, "Insert Number ${iPos+1}").then((String sResult) =>
          print(sResult));        

        fListTable(oDb, "Select after Insert number ${iPos+1}").then((String sResult) =>
          print(sResult));
      }
    });
  });
}  

async.Future<String> fClearTable(oDb) {
  async.Completer oCompleter = new async.Completer();
  oDb.execute("DELETE FROM test01").then((oResult){
    oCompleter.complete("Table has been cleared");
  });
  return oCompleter.future;
}

async.Future<List> fListTable(oDb, sMsg) {
  async.Completer oCompleter = new async.Completer();
  oDb.query("SELECT * FROM test01").toList().then((lResult){
    String sResult = "$sMsg = $lResult";
    oCompleter.complete(sResult);
  }); 
  return oCompleter.future;  
}

async.Future<String> fInsertData(oDb, sMsg) {
  async.Completer oCompleter = new async.Completer();  
  oDb.execute("Start Transaction").then((oResult){
    String sName;
    for (bool tFound = true; tFound;) {
      int iPos = rand1.nextInt(10);
      sName = lgNames[iPos];
      tFound = false;    // init
      for (iPos = 0; iPos < lgUsed.length && !tFound; iPos++){
        tFound = (sName == lgUsed[iPos]);
      }
    }
    lgUsed.add(sName);
    String sSql = """INSERT INTO test01 (name)
      VALUES ('$sName')""";
    print("$sSql");
    oDb.execute(sSql).then((oVal){
      oDb.execute("COMMIT").then((oVal){
        oCompleter.complete(sMsg);
      });
    });
  });
  return oCompleter.future;
}

プログラムの目的は、3 回ループして次のことを行うことです。 a) テーブルを選択する b) テーブルに行を挿入する。c) テーブルを選択

プログラムからの出力は、最後に 3 つの Insert がすべて同時に表示されていることを明確に示しています。

プログラムからの出力は次のとおりです。

Connected to database
Table has been cleared
Select before Insert number 1 = []
INSERT INTO test01 (name)
  VALUES ('Vern')
Select after Insert number 1 = []
Select before Insert number 2 = []
INSERT INTO test01 (name)
  VALUES ('Peter')
Select after Insert number 2 = []
Select before Insert number 3 = []
INSERT INTO test01 (name)
  VALUES ('Robert')
Select after Insert number 3 = []
Insert Number 1
Insert Number 2
Insert Number 3

プログラムの終了時に psql で選択すると、次のように表示されます。

testdb=# select * from test01;
 id  |  name
-----+--------
 157 | Vern
 158 | Peter
 159 | Robert
 (3 rows)

私が欲しいIEを達成する方法はありますか?挿入後の選択では、テーブルに新しい値が表示されますか?

関連するコメントは大歓迎です。

4

1 に答える 1

5

まず、Future が Dart でどのように機能するかについての素晴らしい記事があります

本当に知っておく必要があるのは、すべての同期コードが完了した後に Futures 内のコードが実行されるということです。さらに、Future は定義上、非同期で完了するため、チェーンされていない限り、ある Future が別の Future より先に完了すると期待するのは合理的ではありません。

つまり、次のようになります。

main() {
  print('first');
  someFutureCall().then((_) => print('second?'));
  someOtherFutureCall().then((_) => print('third?'));
  print('last?');
}

これにより、次のように出力されます: 'first' と 'last?' その後、2 つの Future は任意の順序で完了することができます。どちらが先に完了するかはわかりません。あなたが知っているのは、同期コードが最初に発生するということだけです。

正しい順序にするには、次のようにします。

main() {
  print('first');
  someFutureCall()
    .then((_) => print('second?'))
    .then((_) => someOtherFutureCall())
    .then((_) => print('third?'))
    .then((_) => print('last?'));
}

したがって、サンプルでは、​​順序が保持されない方法で Future を使用しています。あなたが欲しいのはこれです:

void main() {
  pg.connect(uri).then((oDb) {
   print ("Connected to database");
   return fClearTable(oDb);
  }).then((String sResult){
    print(sResult);      
    return Future.forEach([0, 1, 2], (i) {
      return fListTable(oDb, "Select before Insert number ${iPos+1}")
       .then((String sResult) => print(sResult))
       .then((_) => fInsertData(oDb, "Insert Number ${iPos+1}"))
       .then((String sResult) => print(sResult))
       .then((_) => fListTable(oDb, "Select after Insert number ${iPos+1}"))
       .then((String sResult) => print(sResult));
    });
  });
}  

Futuresの API ドキュメントも参照してください。

于 2013-04-26T21:58:06.377 に答える