Ten Years On

It’s now ten years since I completed my PhD, “Design Reuse in Human-Computer Interaction and Software Engineering”. I completed the bulk of the report (compiled from earlier papers, but with a lot of tidying up and tying together) in early 2001, submitted it for review (by two external judges) in May, received the feedback in August, revised it and submitted it on September 7. I received a balloon at some point and went to the pub with some PhD buddies and one of our supervisors.

For the first time, here is my PhD online: http://mahemoff.com/paper/thesis.pdf

I’ve sent it on request, but never got around to publishing it. I was told early on you’re required to make five copies of your PhD because five people will ever read it (Your supervisor, your other supervisor, your reviewer, your other reviewer, and your mum), so I never thought much of the actual thesis document. The papers are really more concise summaries of individual components. But I never did a postdoc, so some things in there never got published as individual papers. And it’s good to have it out there anyway, instead of sitting in a library.

I learned a lot about research and its presentation, but I also learned early on that an academic life was not for me. I’m glad I worked on something I was able to use as a practitioner during and after the PhD.

Relevant

WebWorkers, Cross-Domain JSONP, and CoffeeScript

Today’s buzzword gotcha is brought to you by WebWorkers, Cross-Domain JSONP, and CoffeeScript. TL;DR: Always use “self” for WebWorker “globals”. And a library.

My Twitter app’s locking the main thread a bit, so thought I could quickly push polling functionality into a WebWorker. Not so fast …

Firstly, WebWorkers don’t do JSONP the normal way. You can’t inject a script because there’s no DOM. This means you can’t even use standalone JSONP libraries, let alone jQuery (which doesn’t even run in a WebWorker, as it assumes DOM presence, and would be a waste of bandwidth anyway).

Fortunately, we can use importScripts(). Conveniently enough, importScripts() can be used anytime and accepts any old string. So the API would actually be useful in the main thread too, but I digress …

So in Plain Old JavaScript, you would do:

javascript
< view plain text >
  1. function go() { doSomething(); }
  2. importScripts("api.twitter.com?callback=go");

Works just fine. But this won’t work in the CoffeeScript equivalent, i.e.:

  1. go = -> doSomething()  ### NOT CALLED
  2. importScripts "api.twitter.com?callback=go"

In fact, Chrome gives a mysterious error “Uncaught undefined”, while Firefox cuts to the chase: “go is not defined”.

The reason is that the CoffeeScript compiler wraps the entire thing in a closure. This is tremendously useful default behaviour, as you don’t have to worry about adding new globals, but can cause problems in situations like this. If the script comes back from Twitter and calls “go()”, where does that actually end up? With the main thread, a CoffeeScript can explicitly bust properties out of the closure using the global namespace, i.e. “window.foo” (or “global.foo” in the case of a server-side Node script). In fact, there’s a solution to this with WebWorkers too. have their own global identity, “self”.

  1. self.go = -> doSomething()  ### FTFY
  2. importScripts "api.twitter.com?callback=go"

Works.

Be sure to use “self” for other WebWorker “globals” too, i.e.:

  1. self.onmessage = (ev) -> doSomething()

Here’s a tiny jsonp library to support this:

So you can say: