loading...
Cover image for Explain Futures and Streams in Dart like I'm Five

Explain Futures and Streams in Dart like I'm Five

allanjeremy profile image Allan N Jeremy ・1 min read

Uh, hi there, (awkward silence). Been a while since I posted here, mostly because a lot has been going on. However, couldn't help but come back to my favorite dev community. Been trying to learn dart and flutter for a week or two now and the concept of futures and streams keeps eluding me, could anyone shed some light?

PS. Will probably be posting a lot of dart questions

Discussion

markdown guide
 

By Dart documentation:

A Future represents a computation that doesn’t complete immediately. Where a normal function returns the result, an asynchronous function returns a Future, which will eventually contain the result. The future will tell you when the result is ready.

and

A stream is a sequence of asynchronous events. It is like an asynchronous Iterable where, instead of getting the next event when you ask for it, the stream tells you that there is an event when it is ready.

I find that sometimes real-world analogies work well for explaining / remembering concepts. Here's one - it's not perfect but it helps me.

Think that you are at one of those modern sushi restaurants where you have a belt going around the room with sushi boats on it. You just sit down and wait till one goes by, grab it and eat. But they also allow you to order carry out.

  • A Future is like the token with a number on it that they give you when you order takeout; you made the request, but the result is not yet ready but you have a placeholder. And when the result is ready, you get a callback (the digital board above the takeout counter shows your number or they shout it out) - you can now go in and grab your food (the result) to take out.

  • A Stream is like that belt carrying little sushi bowls. By sitting down at that table, you've "subscribed" to the stream. You don't know when the next sushi boat will arrive - but when the chef (message source) places it in the stream (belt), then the subscribers will receive it. The important thing to note is that they arrive asynchronously (you have no idea when the next boat/message will come) but they will arrive in sequence (i.e., if the chef puts three types of sushi on the belt, in some order -- you will see them come by you in that same order)

From a coding perspective -- both Futures and Streams help you deal with asynchrony (where things don't happen instantly, and you don't know when you will get a result after you make a request).

The difference is that Futures are about one-shot request/response (I ask, there is a delay, I get a notification that my Future is ready to collect, and I'm done!) whereas Streams are a continuous series of responses to a single request (I ask, there is a delay, then I keep getting responses until the stream dries up or I decide to close it and walk away).

Hope that helps.

 

I had read the docs but was still unsure about the concepts. Your analogies have shed some light on the topic. Especially on streams.

The difference is that Futures are about one-shot request/response (I ask, there is a delay, I get a notification that my Future is ready to collect, and I'm done!) whereas Streams are a continuous series of responses to a single request (I ask, there is a delay, then I keep getting responses until the stream dries up or I decide to close it and walk away).

This answers the questions I've asked in my previous two replies above. So, thanks. Knowing this I can now explore creating streams as tests since it somewhat makes sense now.

 

Best explanation ever. I now fully understand. Thanks

 

This really clarified things for me thanks a ton!

 

This may have already been answered pretty well, and I'm not sure a 5 year old will get this, but I'd like to have a go with some code snippets.

So...

Futures are to Dart, what Promises are to JavaScript.

In other words, I give you my word that when the time is right, I will provide the full result.

In JavaScript, we would have something along the lines of:

const asyncRequest = () => new Promise(function(resolve, reject) {

  setTimeout(function() {
    resolve("Completed");
  }, 1000);

});

asyncRequest().then((result) => console.log(result));

And in Dart:

import 'dart:async';

asyncRequest() {
  var completer = new Completer();

  new Timer(new Duration(seconds: 1), () {
    completer.complete("Completed");
  });

  return completer.future;
}

void main() {
    asyncRequest().then((result) => print(result));
}

With streams however:

Streams are to Dart, what Events are to JavaScript.

For example, typing on the keyboard creates a stream/sequence of keypresses, which are processed using events

In JavaScript, we would have something along the lines of:

document.querySelector('#input')
    .addEventListener('keypress', (e) => console.log('Value changed.'));

And in Dart:

import 'dart:html';

void main() {
    querySelector('#input')
        .addEventListener('keypress', (e) => print("Value changed"));
}

with another whereby each letter is streamed as a sequence of single characters.

import 'dart:async';

void main() {
  List<String> alphabets = 'abcdefghijklmnopqrstuvwxyz'.split('');
  var stream = new Stream.fromIterable(alphabets);

  stream.listen((data) => print(data));
}

Hope this enlightens somehow.

 

Streams are to Dart, what Events are to JavaScript.

This!! This right here clarified the streams concept. Thanks.

In the case of streaming each key in the code sample, where would you generally use the stream? Since in this case I assume the split() is similar to the js one, so it'd do that synchronously. The example does clarify the concept, I'm just curious as to what use cases there would be

 

Hey @allanjeremy , this stream has several applications. For example on the UI you could be simulating a text typing effect. See this DartPad for example.

Hey Jermaine, thanks for sharing. Managed to wrap my head around the concept through all the great responses

 

TL/DR:

Futures are like Promises. In fact, when Dart compiles into JavaScript, Futures are replaced with Promises.

Streams are essentially a subscription event handler.

In AngularDart, I'll use a Stream in a component like this:

  @Output()
  Stream<bool> get onButtonClose => _onButtonClose.stream;
  final StreamController<bool> _onButtonClose = new StreamController<bool>.broadcast();

And in the component's element I'll wrap an attribute of the same name as the variable tagged with the @Output annotation in parentheses:

<component (onButtonClose)="closeUI($event)"></component>

This means when the Stream has an event, it will trigger the closeUI() function and pass the event object as a parameter. Note: The Stream is set to pass objects of type bool (Stream<bool>), so the closeUI function must accept bool as a parameter.

That's the basics, but not for a five year old.

So let me go simpler:

A Future is something you can hold onto until the thing you actually want is available.

A Stream is a subscription, whenever something of interest is available, it will be passed through the Stream.

 

Great, thanks. Understood Futures from the promises example. I really didn't get streams until the last sentence.

Still trying to grasp how I'd use them based on your explanation. So do streams generally take futures as values? Or how exactly do they work?

Going by

whenever something of interest is available, it will be passed through the Stream.

Wouldn't a future just work equally as well? I may be a little confused here. I can see use cases for futures, but still confused on how or when I'd need a stream. Do you mind giving an example use-case in production?

 

I type
asyncRequest().then((result) => print(result));
and it works.

If I want to use result outside this line how to proceed?
I've tried this, but it didn't work:

String x;
asyncRequest().then((result) => x=result);
print (x);

It shows x=null;

 

All in all, all the comments have given me different perspectives and clarified what was unclear about the concepts. I'm sure this will benefit someone else in future. Cheers guys

Thanks :)