4 ms·
I'm comparing instead against an approach where you break down all relevant events into JSON, and then push those into a global fully-functional "event handler"
by gruseom 13y ago
I'm comparing instead against an approach where you break down all relevant events into JSON, and then push those into a global fully-functional "event handler" function that translates events (along the "world state") into a set of DOM manipulation primitives
How common is this approach? I'd be very interested to hear people's experiences with it. It's what we do, except we run the global event processor on a JS timer so that it works like a game loop picking items off a queue. Our DOM event handlers (the things you call addEventListener with) are all trivial stubs that simply create JSON descriptions of events as they happen and append them to that queue. We tried many different approaches before we hit on this, and it works surprisingly well in the two hardest areas: managing complexity and keeping the UI snappy.
You can also create perceived concurrency this way: you do a little work on an item in the queue and then, if it's not done, put it back at the back of the line. That's how we do the "time-sensitive operations" you mention.
I'm not sure what to call this design. I think of it as a state machine, but that's a metaphor rather than a precise description.
- abecedarius 13y agoAre you familiar with E? It basically works like this, plus built-in, transparent promises. http://www.erights.org/elib/concurrency/event-loop.html http://www.erights.org/elib/concurrency/event-loop.html outlines why you might settle on this model. The messages about coroutines linked at the bottom argue against things like core.async. (This all long precedes core.async, but Concurrent ML had that kind of design.) I've only done simple things in JS and don't understand what advantage you're getting by queueing events yourself, since JS already runs an event loop. Is it that you can inspect the queue and drop/modify events superseded by subsequent ones? I tried to do that once and it didn't help, but I've gotta admit I'm the opposite of an expert on JS UIs.
- swannodette 13y agoAs far as I understand CSP is not a coroutine model - though you can express it. Hoare covers this in his '78 paper. As far as delving into its utility for UI, it's worth looking at Pike's work and the Concurrent ML eXene work.
- abecedarius 13y agoYes, I've read the Pike and CML, they're good work. Haven't got around to Hoare 1978, and I don't see it online, but as I understand it, threads = coroutines + interleaving; adding interleaving won't reduce the problems in reasoning about code. If the distinction is that processes don't share state, I don't think that works, since you can implement mutable cells using channels and processes. (Obviously it's less of a problem than, say, pthreads, if that's the only mutable shared state.)
- gruseom 13y agoThis Hoare 1978? http://www.cs.ucf.edu/courses/cop4020/sum2009/CSP-hoare.pdf http://www.cs.ucf.edu/courses/cop4020/sum2009/CSP-hoare.pdf On my list to read too.
- abecedarius 13y agoOh, good. (It was late and I gave up after the first page of google.)
- gruseom 13y agoThanks for the link! I shall read it. I wrote a reply that is perhaps a bit too long to put here, so I put it at http://pastebin.com/4nN04Hj3 http://pastebin.com/4nN04Hj3 instead. The short answers are: (1) this event loop is different from the browser's event loop because it's app-specific. Having a single interception point where you translate the browser event stream (mousedown, keypress etc.) into higher-level app-specific terms, and then write the rest of the UI in the latter, is a strategy for reducing complexity—an application of bottom-up programming to web UIs, really; and (2) emphatically yes, making the "official" event loop trivial and running all the complex stuff off your own app-specific loop allows you to control how much processing to do and when, which can be a way out of some thorny performance problems (such as sluggish scrolling) as well as an easy path to simulated concurrency. It's interesting that you should have said "drop/modify events superseded by subsequent ones" because that's precisely what led us to this design originally—we were desperate, in fact, for a way to do that. The bottom-up programming aspect and the concurrency aspect only became clear later.
- abecedarius 13y agoI think I read that E's promises came out of experience with UI programming too -- that they invented http://erights.org/elib/distrib/pipeline.html http://erights.org/elib/distrib/pipeline.html for the sake of sanely programming snappy UIs for Xanadu. Sounds like I gave up too easily on queuing and pruning events, or it was the particular platform (touch tracking on Nexus 7 and first-gen iPad). Thanks for the experience report. :-) It might help me remember this when I get back to http://wry.me/hacking/lissajous.html http://wry.me/hacking/lissajous.html to finish & polish -- I let it get all cut-and-pastey in doing drag-controls for the first time.
- gruseom 13y agoI've now read those pages. I knew about E for its capability model but not at all for its concurrency model, which is indeed very interesting (more interesting, to me) and close to home. There's a presentation mentioned there that I found slightly clearer than the page itself; the link is dead but it can be read here: http://web.archive.org/web/20070626045558/http://www.drjava.de/e-presentation/html-english/img0.html http://web.archive.org/web/20070626045558/http://www.drjava.... This model deserves to better known, especially since all this stuff is in play again nowadays. Are there other implementations of it? (Node.js might be a natural platform, given its event loop and the popularity of promises there.) I also wonder what the biggest differences are between it and Erlang. In your pipelining example (t3 := (x <- a()) <- c(y <- b())), what happens if the messages arrive out of order? (Or does the system prevent that and if so how?) I suppose if an expression can't be evaluated because a promise hasn't resolved yet, it could just go back to the end of the queue and eventually everything will bubble up? Also: that Xanadu? Wow, no idea. Edit: I forgot another thing I wanted to include in this omnibus comment. The paper "On the Development of Reactive Systems" that's mentioned at your first link and which can be found at [1], starts off with a very interesting and exciting distinction between "transformational" systems (which take inputs and transform them into outputs) and "reactive" systems that "are repeatedly prompted by the outside world and [whose] role is to continuously respond to external inputs. A reactive system, in general, does not compute or perform a function, but is supposed to maintain a certain ongoing relationship, so to speak, with its environment". I think this is extraordinarily lucid and that the authors are right to talk about concurrency—and probably complexity in general—in the latter sort of system as being a different challenge than in the former. Unfortunately, the paper quickly sinks into a pit of software process goo and never returns. A little Googling gives me the impression that important technical work did come out of it, though, and if anyone knows what the high points are I would like to see them. [1] http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/ReactiveSystems.pdf http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Reac...