2

Stream を返す関数を実装しています。エラー処理の実装方法がわかりません。ベスト プラクティスは何ですか?

Future を返す関数の場合、同期エラーをスローしないことがベスト プラクティスです。これは Stream を返す関数にも当てはまりますか?

これが私が考えていることの例です:

Stream<int> count() {
   var controller = new StreamController<int>();
   int i = 0;
   try {
     doSomethingThatMightThrow();
     new Timer.repeating(new Duration(seconds: 1), () => controller.add(i++));
   } on Exception catch (e) {
     controller.addError(e);
     controller.close();
   }
   return controller.stream;
}
4

2 に答える 2

2

一般に、これはストリームにも当てはまります。主な考え方は、ユーザーはエラーを 1 つの方法で処理するだけでよいということです。あなたの例は、すべてのエラーをストリームに移動します。

即時エラーの方がよい場合もあります (たとえば、エラーがプログラミング エラーによるものであり、とにかく処理されるべきではない場合や、ストリームがエラーを生成しないことを保証したい場合など) が、ストリームを介してエラーを送信する場合があります。ほとんどの場合、良いことです。

小さな点: Stream は通常 (例外があります)、誰かがリッスンを開始するまでデータを生成しません。あなたの例では、リスナーが存在するかどうかさえわからなくても、タイマーを開始しています。この例は縮小されており、実際のコードを表していないと思いますが、注意が必要です。解決策は、一時停止とサブスクリプションの変更に StreamController のコールバックを使用することです。

于 2013-03-29T12:51:43.433 に答える
1

Florian のコメントを取り入れて例を更新しました。

私の実際の使用例では、結果をバッファリングしたくないので、ストリームが一時停止している場合は UnsupportedError をスローしています。

無限ストリームではなく、終端ストリームにしました。

この関数のユーザーが数秒後に非同期でリスナーを追加すると、最初の 2 つの結果が失われます。彼らはこれをすべきではありません。それは明確に文書化するものだと思います。おそらく、最初のデータが受信された後、クローズが受信される前にサブスクライブ状態が変更された場合、エラーをスローすることもできます。

Stream<int> count(int max) {
   var controller = new StreamController<int>(
           onPauseStateChange: () => throw new UnsupportedError('count() Stream pausing not supported.'));
   int i = 0;
   try {
     doSomethingThatMightThrow();
     new Timer.repeating(new Duration(seconds: 1), () {
        if (!controller.hasSubscribers)
           return;
        controller.add(i++);
        if (i >= max)
           controller.close();
     });
   } on Exception catch (e) {
     controller.addError(e);
     controller.close();
   }
   return controller.stream;
}
于 2013-03-29T21:01:51.637 に答える