0

getObject()を使用してデータ型を定義する方法とオブジェクト(レコード)を返す方法を知りたいです。現在、結果(レコード)を取得する関数の外で使用できる唯一の方法は、結果を使用して別の関数を呼び出すことです。そうすれば、データ型を指定する必要はありません。ただし、値を返したい場合は、データ型を定義する必要があり、それが何であるかがわかりません。「ダイナミック」を試しましたが、うまくいかなかったようです。例えば ​​":

fDbSelectOneClient(String sKey, Function fSuccess, String sErmes) {
  try {
    idb.Transaction oDbTxn      =   ogDb1.transaction(sgTblClient, 'readwrite');
    idb.ObjectStore oDbTable    =   oDbTxn.objectStore(sgTblClient); 
    idb.Request     oDbReqGet   =   oDbTable.getObject(sKey);
    oDbReqGet.onSuccess.listen((val){
      if (oDbReqGet.result == null) {
        window.alert("Record $sKey was not found - $sErmes");
      } else {
    ///////return oDbReqGet.result;    /// THIS IS WHAT i WANT TO DO
        fSuccess(oDbReqGet.result);    /// THIS IS WHAT i'm HAVING TO DO  
      }});
    oDbReqGet.onError.first.then((e){window.alert(
      "Error reading single Client. Key = $sKey. Error = ${e}");});
  } catch (oError) {
    window.alert("Error attempting to read record for Client $sKey.
       Error = ${oError}");    
  }
}
fAfterAddOrUpdateClient(oDbRec) {
  /// this is one of the functions used as "fSuccess above
4

1 に答える 1

1

他の誰かがかつて言ったように(誰を思い出せない)、非同期APIを使い始めたら、すべてが非同期である必要があります。

これを行うための典型的な「ダート」パターンは、Future+Completerペアを使用することです(ただし、上記の質問で行ったことには本質的に問題はありません。スタイルの問題です...)。

概念的には、fDbSelectOneClient関数はより完全なオブジェクトを作成し、関数はを返しますcompleter.future。次に、非同期呼び出しが完了したら、を呼び出しcompleter.completeて、に値を渡します。

関数のユーザーはfDbSelectOneClient(...).then((result) => print(result));、結果を非同期的に利用するために呼び出します

上記のコードは、次のようにリファクタリングできます。

import 'dart:async'; // required for Completer

Future fDbSelectOneClient(String sKey) {
  var completer = new Completer();

  try {
    idb.Transaction oDbTxn      =   ogDb1.transaction(sgTblClient, 'readwrite');
    idb.ObjectStore oDbTable    =   oDbTxn.objectStore(sgTblClient); 
    idb.Request     oDbReqGet   =   oDbTable.getObject(sKey);

    oDbReqGet.onSuccess.listen((val) => completer.complete(oDbReqGet.result));
    oDbReqGet.onError.first.then((err) => completer.completeError(err));
  } 
  catch (oError) {
    completer.completeError(oError);
  }

  return completer.future; // return the future
}

// calling code elsewhere
foo() {
  var key = "Mr Blue";

  fDbSelectOneClient(key)
    .then((result) {
      // do something with result (note, may be null)
    })
    ..catchError((err) {  // note method chaining ..
     // do something with error
    };
}

このfuture/completerペアは、1回のショットでのみ機能します(つまり、onSuccess.listenが複数回呼び出された場合、2回目は「Futurealreadycompleted」エラーが発生します(関数名に基づいて、次のように仮定しました)fDbSelectOneClient。単一のレコードのみを選択することを期待しています。

単一のfutureから値を複数回返すには、Futureの新しいストリーム機能を使用する必要があります。詳細については、http: //news.dartlang.org/2012/11/introducing-new-を参照してください。ストリーム-api.html

また、先物とコンプリーターはジェネリックスをサポートしているため、次のようにリターンタイプを強く入力できることにも注意してください。

// strongly typed future
Future<SomeReturnType> fDbSelectOneClient(String sKey) { 
  var completer = new Completer<SomeReturnType>(); 

  completer.complete(new SomeReturnType());
}

foo() {
  // strongly typed result
  fDbSelectOneClient("Mr Blue").then((SomeReturnType result) => print(result));
}
于 2013-02-04T08:53:51.473 に答える