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,一切都需要异步。

执行此操作的典型“Dart”模式是使用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
    };
}

这对未来/完成者仅适用于一次拍摄(即,如果onSuccess.listen多次调用,那么第二次您将收到“未来已完成”错误。(我根据函数名称做了一个fDbSelectOneClient假设您只希望选择一条记录。

要从单个未来多次返回一个值,您可能必须使用 Future 的新流功能 - 请参阅此处了解更多详细信息:http: //news.dartlang.org/2012/11/introducing-new-流-api.html

另请注意,Futures 和 Completers 支持泛型,因此您可以强类型化返回类型,如下所示:

// 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 回答