question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to make an originating source stream with no starting data?

See original GitHub issue

Summary

How would you create a simple base stream for emitting arbitrary data that doesn’t exist yet? All the examples in the documentation seem to begin with either a dom event, or an existing dataset. I found one very basic example on StackOverflow that seems to do more-or-less what I’m after, but I can’t seem to locate the create method (maybe it doesn’t exist anymore?).

Happy to work directly with Stream if that’s what I need to do, but again, can’t find any documentation that demonstrates how this works beyond the raw API descriptions of Stream, Sink, Disposable, Scheduler. It would be nice to have at least one simple example that shows how these pieces fit together for those of us who are not already streaming masters.

Would be even happier to use some “functional” judo to create it, if that’s possible. I feel like maybe there’s something here about the never stream merged or switched or something that could get me going, but I just can’t come up with anything myself that even hints at a solution.

Versions

  • most.js: 1.7.2

Code to reproduce


// something like this

const log = x => console.log(x)

const createStream = () => {
  // ??????
}

const myStream = createStream()
myStream.observe(log) 
myStream.next('some value')

// log: 'some value'

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:3
  • Comments:45 (8 by maintainers)

github_iconTop GitHub Comments

3reactions
axefrogcommented, Oct 17, 2017

Hey @skylize, I’ve been observing silently on the sidelines and thought I’d throw in a very simple source I use for a number of my own use cases, in order to show you how trivial a simple source can be to write. Brian is correct in what he’s saying about creating your own sources for your personal use cases. Once you realise how incredibly easy it is, you’ll probably find yourself doing so regularly.

This little example is kind of the equivalent of now(foo) in @<span />most/core (or just(foo) in cujojs/most), but allows you to supply a function that supplies the initial value when the stream is first subscribed to, which means you can latebind the creation of the value, rather than supplying it up front. This can be handy if the stream isn’t guaranteed to be observed, and the construction of the stream graph is complex and may be a performance concern. Use of closures means it can also be used as a simple method for generating a proxy stream (i.e. getting access to the stream reference before you are able to initialize one of its dependencies).

import { join, propagateTask } from '@most/core';
import { asap } from '@most/scheduler';

export function defer (f, seed) {
  return new Resolve(f, seed);
}

export function deferStream (f, seed) {
  return join(defer(f, seed));
}

export class Resolve {
  constructor (resolve, seed) {
    this.resolve = resolve;
    this.seed = seed;
  }

  run (sink, scheduler) {
    return asap(propagateTask(task, this.resolve(this.seed), sink), scheduler);
  }
}

function task (time, value, sink) {
  sink.event(time, value);
  sink.end(time);
}

… and now you have a stream source. This example uses it to generate a random number that resolves a new random number for every observer. There are many ways to skin a cat; this is just for demonstration purposes.

const max = n => a => Math.floor(a * n);
const num = map(max(100), defer(Math.random));
3reactions
briancavaliercommented, Oct 18, 2017

Hi @skylize. I wanted to try to address what seems like an underlying assumption you may have made about what a most.js Stream is. I’ll be direct, and I hope you’ll bear with me. I really do think this will help us help you with your use case.

I’m looking to re-implement EventEmitter as purely a stream with no emitter underneath

This isn’t a goal of most.js. A most.js Stream is neither an event emitter, nor a pub sub topic, nor a queue. it’s not a goal of most.js to provide an API to create a Stream and then imperatively push values into it from the outside.

A most.js Stream is a declarative data structure representing a sequence of events–values that occur at specific times. Declaring (i.e. creating) a most.js Stream is conceptually equivalent to declaring the sequence of events that it contains.

This declarative programming model can be a different way of thinking but also has many advantages. For example, it avoids publisher/subscriber race conditions of event emitters, as well as the potential for infinite buffering that arises from trying to avoid such race conditions.

So, most intentionally deals only in declarative event streams.

Other community libraries build on that declarative base to provide additional functionality. For example, there are libs to provide declarative Stream sources for various things, like the DOM.

That’s why most-subject and @most/create exist as separate packages. They do not represent the primary declarative usage model of most.js. Some third-party libs, like React, have programming models that essentially require imperatively pushing events into a stream. In such focused instances, it may be necessary to accept the tradeoffs of packages most-subject or @most/create in order to bridge from imperative to declarative.

Another option is implementing the Source/Sink API directly, as many community packages such as most-subject do. I’m sorry that the documentation for doing this is insufficient currently. We would be happy to help with that, and there are several examples in the mostjs-community repo.

I hope that helps, and I invite you to join us in the gitter chat to discuss your particular use case.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Streams—The definitive guide - web.dev
The Streams API allows JavaScript to programmatically access streams of data received over the network and process them as desired.
Read more >
Creating streams in Dart - Dart programming language
A stream is a sequence of results; learn how to create your own.
Read more >
Events and streams | Datastream | Google Cloud
Streams, objects, and events have data and metadata associated with them. ... change to the data itself from the object originating from the...
Read more >
Implementing the Web Streams API in Node.js - James M Snell
Every ReadableStream has what is referred to as an "underlying source" -- an object from which the streaming data originates, and a "controller" ......
Read more >
Stream Processing, Streaming Data, and Data Pipelines
A streaming data pipeline flows data continuously from source to destination as it is created, making it useful along the way. Streaming data...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found