Programming well in Javascript

With my background as a theoretical computer scientist, I’m a terrible programmer (Back in college taking operating systems, my team got special mention for having the most elegantly designed operating system, all built around a single semaphor API.  Of course it only executed for 30 seconds before crashing).  But sometimes, when I can’t convince any of my graduate students that it’s important enough, I have to step in and try to fix up some of our tools myself.    My Haystack group does a lot of HCI research on the web, which means a lot of our tools are in Javascript.   As I’ve been working to tweak those tools, two really obvious flaws in the environment, that pretty much force bad programming practice, have been jumping up repeatedly.   I’m curious why these flaws haven’t been fixed, and whether any of you readers have advice for overcoming them.

Both flaws stand out in some work I’m doing on our Dido system (a client-side WYSIWYG tool for managing data and its visualizations using Exhibit).  I’m trying to add a “Wizard”—a wrapper that will walk people through a sequence of interactions.  Each of which is already accessible using a toolbar, and pops up a dialog for the user to perform some operation, but the Wizard will save the user figuring out the toolbar by programatically opening each of the dialogs in sequence.

I’m using jquery-ui for the dialogs. The dialogs themselves are written in html, then buttons are defined with Javascript behaviors attached to them.  And this raises the first problem—fragmentation of modules.  Any dialog consists of an html part and a Javascript part, which pretty much forces them to go into separate files.  Which means you can’t get a unified picture of the “component”—its Javascript and html.  The html needs to be part of the main page (unless I want to go off and fetch auxiliary html content) while the Javascript should be in a separate js file.  In theory, I could write js code to dynamically generate the html I need, but this is really contrary to the notion that the dialog is in fact static html, and I should be able to look at it that way.  Given Javascript’s allergy to newlines in strings, it’s hard for me even to include the static html as a blob in the js.  Obviously I’m not the first person to be in this situation.  Are there any nice ways to package a “library” of Javascript plus html as a single, editable file that can then be included via a link from the main document?

The second problem emerges from the asynchronous interaction model of javascrit.  Like any browser-javscript library for this user interaction, jquery-ui is asynchronous.  My javascript can make a call to open a dialog, but then that thread of computation ends and interaction with the dialog is handled through callbacks that are invoked when dialog buttons are clicked.  These callbacks have no automatic connection to the thread that opened the dialog.  My Wizard doesn’t want to do things this way: I want to invoke the dialog, then have the wizard pick up when the dialog is closed.

Of course there’s a way to do this in javascript—continuation passing.  I pass in a function that should be invoked when the dialog is closed, that picks up Wizarding where the dialog open left off.  This works just fine.  But I don’t like it.  The unrestricted passing of continuations lets people deal with them arbitrarily—which permits cool hacks but also gives the programmer autonomy to do hard-to-understand things.  It’s like bringing back goto—it can be used properly, but generally isn’t.   The last time I had to explicitly pass in a “return address” was when I was working on the assembly-language-based recalculation engine for Excel version 2.  High level programming languages are supposed to insulate me from managing the call stack!

And with the right language elements, this should be possible even in an asynchronous environment.  The semantics of a subroutine call are that computation should pick up on the next line when the subroutine completes.  So what if the completion of that subroutine is driven by an asynchronous event?  i.e., the dialog subroutine is one that starts by opening the dialog box, then yields until a button in the dialog is clicked, then picks up processing to figure out what to do about the clicked button.  And if it can remember that it is “picking up” from a previous thread, then that thread can return to the function that originally called the dialog.  I’d love to see javascript introducing language elements to support this, and I’m puzzled about why they haven’t already done so.  If any of you know any ways to cope with this, I’d love to hear.

9 Responses to “Programming well in Javascript”

  • Tom Lieber says:

    You can use generators to implement coroutines, though it looks like only Firefox supports generators. The way they’re added to the language, they don’t well insulate you from the call stack, but they would let you write functions in that synchronous style.

  • Adam Marcus says:

    Fellow CSAILer Yang Zhang pointed me at TameJS (GitHub). It adds two primitives(await and defer) as well as a pre-processor to your javascript files that allows you to program without continuation-passing style, but compile down to it.

  • David Karger says:

    Adam, TameJS looks nice, but only halfway nice. It offers a nice pair of functions, “await” to wait for completion of a subroutine and “defer” that lets the subroutine use a callback to notify that waiting caller that it can continue. But it appears to require a compile step to produce js from the TameJS source. And if you’re going to compile, you might as well do away with exposed callbacks altogether, instead compiling a traditional “return” statement into an appropriate callback. As I asserted in my post, I think this elimination of programmer-authored callbacks would, like elimination of gotos, produce more nicely structured code in general.

  • Max K. says:

    Thanks Adam for the link. Though of course it’s possible,
    I haven’t gotten TameJS to work in the browser,
    so it’s not going to be very useful to Haystack. When running JS on the server,
    as in node.js programs, things are different. First, there is more need
    for “exotic” concurrency patterns, such as parallel network lookups, pipelined
    RPC calls, timing out slow operations,”background operations,” etc. TameJS and
    things like it handle those patterns pretty well, but usually concurrency patterns
    in the browser are more straight-line sequences. Second, when programming
    on the server, you’re also free to change the interpreter. So there are projects like
    Node Fibers that
    change the V8 interpreter enough to enable something that looks more like threading.
    Of course, this leaves the state of JS on the client unimproved. The “Harmony” ECMAscript
    proposal might include generators and iterators, potentially useful here.

  • Timothy says:

    Surprised that no one has suggested emscripten yet…

  • [...] Source: JavaScript – Google Blog Search [...]

  • Have you ever tried out server side javascript? Currently I’m making some tests with node.js, very useful !

    On the page http://www.nodejs.org are cute examples

    ————
    Fernausbildung

  • The biggest problem with TameJS for me is, the modification it does on the source code makes debugging harder.

    I use the step module when writing nodejs applications ( search “creationix / step” on github ). With the help of it I can avoid the dreaded “spaghetti code” effect.

    Async js coding and callbacks are not a problem for me anymore.
    I have also written an async loop module, but did not uploaded it to github. Drop me a mail if you are interested.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>