上記の質問は Dart Google+ コミュニティで提起されましたが、明確な回答が得られなかったので、ここで質問を繰り返したいと思いました。Dart コミュニティからの投稿は次のとおりです。
https://plus.google.com/u/0/103493864228790779294/posts/U7VTyX5h7HR
では、エラー処理の有無にかかわらず、これを行う適切な方法は何ですか?
上記の質問は Dart Google+ コミュニティで提起されましたが、明確な回答が得られなかったので、ここで質問を繰り返したいと思いました。Dart コミュニティからの投稿は次のとおりです。
https://plus.google.com/u/0/103493864228790779294/posts/U7VTyX5h7HR
では、エラー処理の有無にかかわらず、これを行う適切な方法は何ですか?
あなたがリンクした質問は、複数のファイルの内容を非同期的に読み取ることに関するもので、これはより難しい問題です。フロリアンのソリューションには問題がないと思います。単純化すると、これはファイルを非同期で正常に読み取るようです。
import 'dart:async';
import 'dart:io';
void main() {
new File('/home/darshan/so/asyncRead.dart')
.readAsString()
..catchError((e) => print(e))
.then(print);
print("Reading asynchronously...");
}
これは以下を出力します:
非同期読み取り... import 'dart:async'; import 'dart:io'; ボイドメイン(){ 新しいファイル('/home/darshan/so/asyncRead.dart') .readAsString() ..catchError((e) => print(e)) .then(印刷); print("非同期で読み取り中..."); }
記録のために、最初の問題に対する Florian Loitsch の (わずかに修正された) 解決策を次に示します。
import 'dart:async';
import 'dart:io';
void main() {
new Directory('/home/darshan/so/j')
.list()
.map((f) => f.readAsString()..catchError((e) => print(e)))
.toList()
.then(Future.wait)
.then(print);
print("Reading asynchronously...");
}
Florian のソリューションの欠点 (またはそうでない) は、すべてのファイルを並行して読み取り、すべてのコンテンツが読み取られたときにのみコンテンツを処理することです。場合によっては、ファイルを 1 つずつ読み取り、1 つのファイルの内容を処理してから次のファイルを読み取りたい場合があります。
これを行うには、future を連鎖させて、前の readAsString が完了した後にのみ次の readAsString が実行されるようにする必要があります。
Future readFilesSequentially(Stream<File> files, doWork(String)) {
return files.fold(
new Future.immediate(null),
(chain, file) =>
chain.then((_) => file.readAsString())
.then((text) => doWork(text)));
}
テキストに対して行われる作業は非同期である場合もあり、Future を返します。
ストリームがファイル A、B、および C を返し、それが完了すると、プログラムは次のようになります。
run readAsString on A
run doWork on the result
when doWork finishes (or the future it returns completes) run readAsString on B
run doWork on the result
when doWork finishes (or the future it returns completes) run readAsString on C
run doWork on the result
when doWork finishes, complete the future returned by processFilesSequentially.
onDone ハンドラーを実行するのではなく、ストリームが完了したときに完了する Future を取得するために、listen ではなく fold を使用する必要があります。