An introduction to eventual operations in Javascript

Instructions

  1. install a Javascript shell, such as this one
  2. visit the test page...
  3. open your javascript shell, with your browser still on the test page
  4. try the commands listed below...

// The default toString implementation in Javascript is pretty useless,
// so switch to using toJSONString
Object.prototype.toString = function () { return this.toJSONString(); }

function () { return this.toJSONString(); }

// Turn the URL for the current page into a remote reference
var page_ = _.connect(window.location.toString())

// The test page is a factory object for constructing a org.waterken.bang.Drum
// object. A Drum is just a counter object that can be incremented. We'll
// create a new Drum by invoking the factory method.
var drum_ = page_.post('subject', [])

// By convention, the name of a variable holding a promise is suffixed
// with an '_' character. When following this convention, you can recognize
// ansynchronous operations by looking for the '_.' character sequence.
var hits_ = drum_.get('hits')

// Since I'm just typing in an interactive shell, the response to the GET
// request sent above will already have been received and processed by the
// time I hit the 'Enter' key.
hits_

0

// Send a POST request to increment the counter...
drum_.post('bang', [ 1 ])

{"$":["org.ref_send.promise.Rejected"],"reason":{"$":["org.ref_send.promise.Indeterminate"]}}

// The post() invocation above is an asynchronous invocation, meaning the
// request was sent, but we didn't wait for the response. The shell echo line
// above shows that the return promise doesn't yet have a resolved value.
// We can send another message right away to query the counter. This GET
// request will be processed after the preceeding POST request.
var hits_ = drum_.get('hits')

hits_

1

drum_.post('bang', [ 2 ])

{"$":["org.ref_send.promise.Rejected"],"reason":{"$":["org.ref_send.promise.Indeterminate"]}}

// If we weren't typing in an interactive shell, we might want to setup a
// callback to be invoked after a promise is resolved. We can do this using the
// when() method. Below, we setup two callbacks: one to be notified if the
// promise is fulfilled with a value; and another to be notified if the promise
// is not fulfilled. Each callback simply prints a message to stdout.
drum_.get('hits').when(function (value) {
    print(value);
}, function (reason) {
    print('rejected: ' + reason);
})

3

// A promise can also be used to queue up future messages. Below, the GET
// request to query the counter is sent on the promise returned by the POST
// request that increases the counter.
var hits_ = drum_.post('bang', [ 3 ]).get('hits')

hits_

6

// You can get runtime information about an object's API by asking for a
// description of the object's class, as is done below...
var meta_ = drum_.get('class').get('*')

// The type URLs shown in your interactive shell will be prefixed with the
// base URL of the particular server you're talking to.
meta_

[ {
    "$" : [ "class" ],
    "bang" : {
      "out" : { "@" : "org.waterken.bang.Drum" },
      "in" : [ { "@" : "number" } ],
      "error" : [  ]
    },
    "equals" : {
      "out" : { "@" : "boolean" },
      "in" : [ { "@" : "object" } ],
      "error" : [  ]
    },
    "class" : {
      "out" : { "@" : "class" },
      "error" : [  ]
    },
    "hits" : {
      "out" : { "@" : "number" },
      "error" : [  ]
    }
  } ]