General Interface is an open source project hosted by the Dojo Foundation

About $Y

$Y allows you to write concise and readable asynchronous code, providing the following capabilities:

  • A standard way to pass and handle callbacks and a standard way to send return values
  • Multiple callbacks per asynchronous call
  • Condition chaining
  • Asynchronous method chaining via automatic parameter resolution
  • Return value chaining

You can use $Y instead of the following "anti-patterns" for asynchronous JavaScript programming:

1. Passing a callback function as a method parameter

2. Using publish-subscribe as an asynchronous callback
 

The following code examples all show an asynchronous method that loads an XML document and sample code that uses the method.

The following code provides an example of anti-pattern 1:

function loadXmlAsync(url, callback) {
var req = new XMLHttpRequest();
    req.onreadystatechange = function() {
        if (callback)
            callback(req.responseXML);
    };
    req.open("GET", url, true):
    req.send();
}

loadXmlAsync("data.xml", function(doc) {
    jsx3.log("Got document: " + doc);
});

As shown in the example, passing a callback function works but can get messy and there is no standard idiom. The following questions may arise:

  • Is the callback function the first method parameter or the last?
  • Is the function required or optional?
  • How are multiple callbacks executed?
  • What is the signature of the callback function?
  • How are return values handled?

The following code provides an example of anti-pattern 2:

this.loadXmlAsync = function(url) {
    var req = new XMLHttpRequest();
    req.onreadystatechange = function() {
        this.publish({subject:"done",
                      doc: req.responseXML});
    };
    req.open("GET", url, true):
    req.send();
};

this.subscribe("done", function(evt) {
    jsx3.log("Got document: " + evt.doc);
});

this.loadXmlAsync("data.xml");

The following issues may arise with anti-pattern 2:

  • Mandatory event subscription is verbose.
  • It is necessary to handle event un-subscription or risk garbage collection issues.
  • An object with an asynchronous API can be used by only one object at a time.
  • To support synchronous completion, the subscription must come before the asynchronous call.
  • The object that publishes the event must implement the jsx3.util.EventDispatcher interface.
  • The publish-subscribe pattern is designed for one-to-many, anonymous, and optional communication. This example is none of these.

The following example shows how to use $Y to implement the function in the previous examples.

this.loadXmlAsync = jsx3.$Y(function(cb) {
    var url = cb.args()[0];
    var req = new XMLHttpRequest();
    req.onreadystatechange = function() {
        cb.done(req.responseXML);
    };
    req.open("GET", url, true):
    req.send();
});

this.loadXmlAsync("data.xml").when(function(doc) {
    jsx3.log("Got document: " + doc);
});

Contents

Searching General Interface Docs

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.