Transforming streams

Listening to a stream captures the sequence of results coming from an event-like action, such as clicking on a button in a web page or opening a file with the openRead method. These results are data that can be processed, but the errors that occur are also part of the stream. Dart can work with streams in a very functional way, such as filtering the results with where or mapping the results to a new stream (for a complete list of these methods, refer to https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:async.Stream). To modify the incoming results, we can also use a transformer; this recipe shows you how to do this (refer to the project transforming_stream).

How to do it...

In our script, we have a list, persons, where the items are themselves lists consisting of a name and a gender. We want to walk through the list and emit a greeting message based on the gender of the person, but if the gender is unknown, we skip that person. The following code shows us how we can do this with a transformer:

import 'dart:async';

var persons = [
  ['Carter', 'F'],
  ['Gates',  'M'],
  ['Nuryev', 'M'],
  ['Liszt', 'U'],
  ['Besançon', 'F']
  ];
  
void main() {

We need to perform the following steps to transform the streams:

  1. To make a stream from the list, use the following code:
    var stream = ne
    w Stream.fromIterable(persons);
    
  2. To define a stream transformer, use the following code:
    var transformer = new StreamTransformer.fromHandlers(handleData: convert);
    
  3. To filter and transform the stream, and listen to its output to process further, use the following code:
    stream
    .where((value) => value[1] != 'U')
    .transform(transformer)
    .listen((value) => print("$value"));
    }
    
    convert(value, sink) {
      // create new value from the original value
      var greeting = "Hello Mr. or Mrs. ${value[0]}";
      if (value[1] == 'F') {
        greeting = "Hello Mrs. ${value[0]}";
        }
        else if (value[1] == 'M') {
        greeting = "Hello Mr. ${value[0]}";
      }
      sink.add(greeting);
    }

After performing the preceding steps, we get the following output:

Hello Mrs. Carter

Hello Mr. Gates

Hello Mr. Nuryev

Hello Mrs. Besançon

How it works...

To turn a list into a stream, we used the fromIterable method as in step 1. Discarding some values from the stream can be done with where; see the first clause in step 3.

Step 2 details how to transform a stream. This method takes an object (here called transformer) of the class StreamTransformer, which allows you to change the contents of the stream. The constructor named fromHandlers takes an optional handleData argument that calls our callback function convert for each value passed from the stream. The convert option builds a new value based on the content of the old value and adds it in place of the old value of the sink variable. Only those transformed values are output on the stream, passed on to listen, and processed there. The sink option is an instance of the abstract class StreamSink, which is a generic destination of data and can be implemented by any data receiver.

There's more...

We have already used transform in this chapter when reading a file with openRead, as shown in the following code:

Stream<List<int>> input = file.openRead();
input
.transform(UTF8.decoder) 
.transform(const LineSplitter())

The inputStream stream is a List<int> list, and thus strongly typed. First, the incoming integers are transformed into a stream of UTF-8 characters, and then the input is split into subsequent lines. Instead of transform, we could have used the map method on the stream as well.

HttpRequest in the browser does not support getting the response as a stream. To work along that pattern, you have to use WebSockets (refer to Chapter 7, Working with Web Servers).

See also

  • Refer to the Reading a file recipe, the second example in the Concatenating files recipe, and the Writing files recipe for more examples on transforming streams
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset