web-dev-qa-db-ja.com

Futureインスタンスから値を取得する

私のデータは次のようなものです:

{
  "five": {
    "group": {
      "one": {
        "order": 2
      },
      "six": {
        "order": 1
      }
    },
    "name": "Filbert",
    "skill": "databases"
  },
  "four": {
    "group": {
      "three": {
        "order": 2
      },
      "two": {
        "order": 1
      }
    },
    "name": "Robert",
    "skill": "big data"
  },
  "one": {
    "name": "Bert",
    "skill": "data analysis"
  },
  "seven": {
    "name": "Colbert",
    "skill": "data fudging"
  },
  "six": {
    "name": "Ebert",
    "skill": "data loss"
  },
  "three": {
    "name": "Gilbert",
    "skill": "small data"
  },
  "two": {
    "name": "Albert",
    "skill": "non data"
  }
}

次の関数を使用しています。

  Future retrieve(String id) async {
    Map employeeMap = await employeeById(id); //#1
    if (employeeMap.containsKey("group")) { //#2
      Map groupMap = employeeMap["group"];
      Map groupMapWithDetails = groupMembersWithDetails(groupMap); #3
      // above returns a Mamp with keys as expected but values 
      // are Future instances.
      // To extract values, the following function is
      // used with forEach on the map
      futureToVal(key, value) async { // #4
        groupMapWithDetails[key] = await value; 
      }
      groupMapWithDetails.forEach(futureToVal); // #4
    }
    return groupMapWithDetails;
   }
  1. データベース(Firebase)から従業員に(a Mapとして)アクセスします
  2. 従業員がリーダーである場合(重要な「グループ」を持っている)
  3. 個別の関数を呼び出すことにより、データベースから満たされたグループ内の各従業員の詳細を取得します。
  4. 関数はFutureのインスタンスである値を持つマップを返すので、それらから実際の値を抽出したいと思います。このため、マップ上でforEachが呼び出されます。ただし、値として取得できるのはFutureのインスタンスのみです。

実際の値を取得するにはどうすればよいですか?

7
Hesh

非同期実行から同期実行に戻す方法はありません。

Futureから値を取得するには、2つの方法があります

コールバックをthen(...)に渡します

theFuture.then((val) {
  print(val);
});

または、async/awaitを使用して構文を改善します

Future foo() async {
  var val = await theFuture;
  print(val);
}
26

await value式が完了するのを待っていません。

forEach呼び出しはマップエントリを実行し、それぞれの非同期計算を開始します。 forEachは関数の戻り値を使用しないため、その計算の将来は破棄されます。次に、非同期計算が完了する前にマップを返すため、マップの値は先物です。最終的には将来のものに変更されますが、いつ完了したかはわかりません。

forEach呼び出しの代わりに、以下を試してください。

await Future.wait(groupMapWithDetails.keys.map((key) async {
  groupMapWithDetails[key] = await groupMapWithDetails[key];
});

これにより、マップ内の各キーに対して非同期操作が実行され、すべてのキーが完了するまで待機します。その後、マップは将来の値ではないはずです。

2
lrn