Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Last active August 29, 2015 14:14
Show Gist options
  • Select an option

  • Save briancavalier/2cc4c091a63324ee66dc to your computer and use it in GitHub Desktop.

Select an option

Save briancavalier/2cc4c091a63324ee66dc to your computer and use it in GitHub Desktop.

Converted from http://plnkr.co/edit/kHrrvjSVTjIaiZpPdbbG?p=preview

See main.js for two ways to do it. To run:

  1. clone the gist into a web servable dir
  2. npm install
  3. open index.html (use http:// not file://)

Note: Although scheduling is configurable in most.js, we haven't yet exposed an API for it. In this case, it's simple enough just to use requestAnimationFrame directly, since it's only being used at the render boundary.

<!doctype html>
<html lang="en" data-rave-meta="package.json">
<head>
<meta charset="UTF-8">
<title>Test</title>
<script src="node_modules/rave/rave.js"></script>
</head>
<body>
</body>
</html>
var most = require('most');
// These two are equivalent
exports.main = function() {
// Create a stream of streams
var blah = most.from([
most.periodic(1000).constant('one').take(5),
most.periodic(1000).constant('two').take(10),
most.periodic(1000).constant('three').take(2)
]);
// Use join to merge nested streams, then observe
blah.join().observe(function(text) {
requestAnimationFrame(function() {
var div = document.createElement('div');
div.innerText = text;
document.body.appendChild(div);
});
});
};
//exports.main = function() {
// // Create a stream by immediately merging
// var blah = most.merge(
// most.periodic(1000).constant('one').take(5),
// most.periodic(1000).constant('two').take(10),
// most.periodic(1000).constant('three').take(2)
// );
//
// blah.observe(function(text) {
// requestAnimationFrame(function() {
// var div = document.createElement('div');
// div.innerText = text;
// document.body.appendChild(div);
// });
// });
//};
{
"name": "example1",
"version": "1.0.0",
"description": "from http://plnkr.co/edit/kHrrvjSVTjIaiZpPdbbG?p=preview",
"main": "main.js",
"author": "[email protected]",
"license": "MIT",
"dependencies": {
"most": "^0.10.2",
"rave": "^0.4.5"
}
}
@benlesh
Copy link

benlesh commented Feb 2, 2015

So in Most.js, the callback to observe is instant, unless something in the handler schedules it otherwise? (i.e. a setTimeout, etc)? If that's the case, having some global rendering scheduler would need to be handled in this manner?

Thank you for your time, BTW.

@briancavalier
Copy link
Author

@Blesh No problem at all, happy to help.

Yes. In general, event propagation in most.js is end-to-end synchronous whenever possible. Some combinators, like delay, debounce, await, etc. will introduce asynchrony because they have to. That is, the "stuff to the left" of a delay() happens in a different call stack than the "stuff to the right" of it.

So, in something like stream.map(...).filter(...).scan(...).observe(func), for each event, the map, filter, scan, and observe will all happen synchronously.

It seems like the right point at which to introduce rAF would be just before, or inside of observe, since it's best to do the bulk of computation before the animation frame, then do the minimum work within the frame.

I've been thinking about a "scheduler hopping" API, similar to what RxJS offers, but I haven't hit a super-compelling use case for it yet. Being able to easy hop to requestAnimationFrame in observe might be the one that pushes me over the edge, though :)

I was thinking something like: var rescheduledStream = stream.reschedule(scheduler). Any further transformations on rescheduledStream would then occur synchronously within whatever mechanism (rAF, etc.) scheduler used. For example: stream.map(...).filter(...).reschedule(rAFScheduler).observe(func).

@benlesh
Copy link

benlesh commented Feb 2, 2015

Yeah. The only use case I can personally think of for leveraging a scheduler at an upstream point in an observable chain would be for doing some sort of advanced merging/zipping/joining of two observable streams in which the context of that operation was important. I have yet to hit such a use case myself, however. There may be other use cases I'm not thinking of.

I think 99.9% of the time though, people want to schedule at the point of side effect, which would be at a subscription or perhaps a tap or do

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment