2020/6/10 Creating streams in Dart

dart:asyncライブラリは他の多くのDart APIにとって重要な二つの型、StreamとFutureクラスを含んでいます。Futureクラスは一つの計算の結果を表し、Streamクラスは複数の計算の結果を表します。streamをlistenすることで結果(データ、あるいはエラーの両方)が届いたことの通知を受けます。listen中にポーズ(一時停止)することもできますし、streamが完了する前にlistenを止めることもできます。

この記事ではstreamの使い方に関しての記事ではありません。streamの作り方に関しての記事です。streamを作るためにはいくつかの方法があります。

  • 既存のstreamを変換する。
  • async*関数(ジェネレータ関数)を用いて一からstreamを作る。
  • StreamControllerインスタンスを用いてstreamを作る。

この記事ではそれぞれのアプローチのサンプルコードを示します。


Transforming an existing stream

一般的なstreamの作り方は、すでにあるstreamのイベントを基にして新しい別のstreamを作る方法です。例えば、入力をUTF-8デコーディングして、既にある「bytesのstream」を「文字列のstream」に変換したいとします。最も一般的なアプローチは、オリジナルのstreamの各イベントの結果を待って新しいイベントを出力する新しいstreamを作ることです。

sample1

/// Splits a stream of consecutive strings into lines.
///
/// The input string is provided in smaller chunks through
/// the `source` stream.
Stream<String> lines(Stream<String> source) 

2020/6/8 dart:async – asynchronous programming(stream))

Stream

Dart APIsのStreamオブジェクトは、複数の非同期処理の結果を表現します。例えば、ボタンのクリックのようなHTMLイベントはstreamを使って届けられます。ファイルもstreamとして読み込むことができます。

Using an asynchronous for loop

Stream APIの代わりに非同期なforループ(await for)を使うことができます。

sample1-1ではStreamクラスのlisten()メソッドでファイルのリストをリッスン(subscribe(購読))しています。listenメソッドの引数に、それぞれのファイルをサーチする関数リテラルを渡しています。

sample1-1の関数について考えましょう。

sample1-1

void main(List<String> arguments) {
  // ...
  FileSystemEntity.isDirectory(searchPath).then((isDir) {
    if (isDir) {
      final startingDir = Directory(searchPath);
      startingDir
          .list(
              recursive: argResults[recursive],
              followLinks: argResults[followLinks])
          .listen((entity) {
        if (entity is 

2020/6/7 Futures and error handling

The Future API and callbacks

FutureAPIの関数は、Futureがcompleteした時の値(あるいはエラー)を処理するコールバック関数を登録します。例えば、

myFunc().then(processValue)
        .catchError(handleError);

then()メソッドのコールバックはFutureが値と共にcompleteした時に実行されます。

catchError()メソッドのコールバックは、Futureがエラーと共にcompleteした時に実行されます。

上記の例では、myFunc()関数の返り値のFutureインスタンスが値と共にcompleteした時、then()メソッドのコールバック(processValue)が実行されます。もしthen()メソッドの中で新たなエラーが発生しない場合、catchError()のコールバックは実行されません。一方で、もしmyFunc()関数がエラーと共にcompleteした場合、then()メソッドのコールバック実行されません。そしてcatchError()メソッドのコールバックが実行されます。


Examples of using then() with catchError()

then()メソッドとcatchError()メソッドをつなげて記述する方法は、Futureを処理する上でよくあるパターンです。そしてそれはtry-catch文と同じように考えることができます。

この後のいくつかのサンプルではこのパターンを見ていきます。

catchError() as a comprehensive error handler

下のサンプルはthen()メソッドのコールバックの中でエラーがスローされて、catchError()でエラーハンドリングする場面です。

myFunc()
  .then((value) {
    doSomethingWith(value);
    ...
    throw("some arbitrary error");
  })
  .catchError(handleError);

もしmyFunc()関数のFutureが値と共にcompleteしたら、then()メソッドのコールバックが実行されます。もしthen()メソッドのコールバックがエラーをスローしたら(上記のサンプルではそうなります)、then()メソッドが返すFutureがエラーと共にcompleteします。そのエラーはcatchError()メソッドで処理されます。

もしmyFunc()関数のFutureがエラーと共にcompleteしたら、then()メソッドが返すFutureもエラーと共にcompleteします。そのエラーもcatchError()メソッドで処理されます。

myFunc()関数内でスローされたエラーも、then()のコールバック内でスローされたエラーも、どちらもcatchError()メソッドにより処理されます。


Error

2020/6/7 dart:async – asynchronous programming

dart:async – asynchronous programming

非同期処理のプログラミングではよくコールバック関数を使って実装しますが、Dart言語では代わりに、FutureクラスとStreamクラスのオブジェクトを使用します。Futureクラスは未来のある時点で結果が提供される「約束」のようなものです。Streamクラスは複数のイベントのような、複数の値を得る方法です。


dart:asyncライブラリはwebアプリとコマンドラインアプリの両方で機能します。ライブラリを使用するときは、dart:asyncライブラリをインポートします。

import 'dart:async';

Version note

Dart2.1からFutureクラスとStreamクラスを使用する際dart:asyncライブラリをインポートする必要はなくなりました。



Future

Futureオブジェクトは、主に非同期なメソッドの返り値として、Dartライブラリの中によく登場します。future(Futureクラスのインスタンス)がcomplete(完了)すると、結果の値を使用することができます。

awaitを使おう(Using await)

Future APIを直接使おうとする前に、awaitを代わりに使用することを考えてください。その方が理解しやすいコードを書くことができます。

下記の関数を考えてみます。runUsingFuture関数は、三つの非同期関数を実行するためにFutureクラスのthen()メソッドを使っています。次の非同期関数を実行する前に、その前の非同期関数の結果を待ちます。

sample1-1

runUsingFuture() {
  // ...
  findEntryPoint().then((entryPoint) {
    return runExecutable(entryPoint, args);
  }).then((exitCode){flushThenExit(exitCode)});
}

 

具体的に、findEntryPoint()関数がcomplete(完了)した時に、その結果を引数entryPointで受け取って、

(entryPoint) {
    return runExecutable(entryPoint, args);
  }

を実行する。runExcutable関数は非同期関数。thenメソッドはFutureインスタンスを返す。その返ってきたfutureがcompleteした時、その結果を引数としてflushThenExit関数に渡して実行される。


sample1-1をawaitを使って書くとsample1-2のようになります。…

2020/3/24 : Dart : Asynchronous programming: futures, async, awaitの訳

Asynchronous programming: futures, async, await

何故非同期なコードが重要なのか?(Why asynchronous code matters)

非同期な処理は、他の処理が終わるのを待つ間、あなたのプログラムを完璧に機能させます。以下に一般的な非同期処理を示します。

  • ネットワークからデータを取ってくる。
  • データベースに書き込む。
  • ファイルからデータを読み込む。

Dartで非同期処理を行うために、Futureクラスとasync、awaitキーワードを使用します。

例:非同期関数の正しく無い使用例

下記のサンプルは非同期関数(fetchUserOrder())の間違った使い方の例です。あとであなたはasync、awaitキーワードを使用してこのサンプルを修正します。このサンプルを実行する前に、どこが間違いなのか考えてみましょう。結果はどうなるでしょうか?

sample1-1

// このサンプルはDartの非同期処理の間違ったコードです。

String createOrderMessage () {
  var order = fetchUserOrder();
  return 'Your order is: $order';
}

Future<String> fetchUserOrder() {
  // Imagine that this