Example use cases

19 views
Skip to first unread message

Tauren Mills

unread,
Jul 19, 2010, 3:36:39 AM7/19/10
to FuturesJS
AJ,

I haven't actually used FuturesJS yet, but plan to try it out soon. I
believe I understand Promises well enough, but I see that much more
than just Promises are supported. I was wondering if you could provide
some example use cases of how you envision each feature of the library
to be used. The descriptions of each feature in the documentation is
rather abstract and it would help to understand them better if there
was a concrete use case.

I'm not asking for sample code, just a description of a scenario where
each feature would be used. For instance, I'd like to better
understand what type of situations would warrant the use a
Subscription instead of a Promise. How about triggers, and
synchronizations? I think I grok immediates and joins, but a
comprehensive set of example use cases would be great!

I hope my question is clear enough. If not, I'd be happy to elaborate.

Thanks,
Tauren




AJ ONeal

unread,
Jul 19, 2010, 11:45:20 AM7/19/10
to futures-j...@googlegroups.com
How would you suggest that I go about adding use cases? On an individual level like this?

Use Cases
========

Futures.promise()
-------------------------

**Use Case**: Mike uses jQuery's $.getJSON(url, data, callback) throughout his app. In his callback he used to list a number of other callbacks.

Before:

    // Get contacts list from facebook
    $.getJSON("http://graph.facebook.com/coolaj86/friends", data, function (friend_list) {
        update_messenger(friend_list);
        update_birthday_calendar(friend_list);
        update_contacts(friend_list);
    });


With FuturesJS:

    // Get friends list from facebook
    var p = Futures.promise();
    $.getJSON("http://graph.facebook.com/coolaj86/friends", data, p.fulfill);
    p.when(update_messenger)
      .when(update_birthday_calendar)
      .when(update_contacts);


Futures.subscription()
--------------------------------

**Use Case**: Mike stores a client-side cache of his user's contacts' information. Some of this information is time-sensitive. 

  * It is perfectly acceptable for data which is up to 15 minutes old to be displayed without waiting for the delay of retrieving the data again.
  * At 15 minutes, however, the data should be updated in the background. 
  * If it's been over 30 minutes the data shouldn't even be displayed until it is updated.

With Promises:

    var p = Futures.promise();
    Contacts.get = function () {
        if (timestamp < 15_minutes) {
            // return the current data set immediately
            return p;
        } else if (timestamp < 30_minutes) {
            // create a new promise for future calls, but return the current data set immediately
            update_contact_list(function (data) {
                p = Futures.promise();
                p.fulfill(data);
            });
            return p;
        } else if (timestamp >= 30_minutes) {
            // create a new promise, discard the current data, and return the data set when fresh
            p = Futures.promise();
            update_contact_list(p.fulfill);
            return p;
        }
    }
    
    // Update the user's display 
    // Similar logic may exist in many places
    document.getElementById('refresh-contacts-button').addListener(function () {
    Contacts.get()
        .when(update_messenger)
        .when(update_birthday_calendar)
        .when(update_contacts)
        .when(update_user_display);
    });


With Futures.subscription:

    var p,
    s = Futures.subscription();
    Contacts.get = function () {
        p = Futures.subscription2promise(s);
        if (timestamp < 15_minutes) {
            // return the current data set immediately
            return p;
        } else if (timestamp < 30_minutes) {
            // create a new promise for future calls, but return the current data set immediately
            update_contact_list(s.deliver);
        } else if (timestamp >= 30_minutes) {
            // create a new promise, discard the current data, and return the data set when fresh
            s.onHoldUntilNextIssue(); // TODO not implemented yet
            update_contact_list(s.deliver);
        }
        return p;
    }
    Contacts.get.subscribe = s.subscribe;
    Contacts.get.hold = s.hold;
    // NOTE: update_contact_list should check itself to return its own current promise
    // rather than calling itself twice while a promise is in progress

    
    // Logic in an Appropriate Place (a model, for example)
    Contacts.get
        .subscribe(update_messenger)
        .subscribe(update_birthday_calendar)
        .subscribe(update_contacts)
        .subscribe(update_user_display);


    // Update the user's display 
    // Similar logic may exist in many places
    document.getElementById('refresh-contacts-button').addListener(function () {
        Contacts.get();
    });


How's that?

Beware, there may be some typos or some logic flaws. I just whipped this up just now. Hopefully it shows the intent well.


TODO: I need to had a reset function to subscriptions that will allow you to put all subscriptions onHoldUntilNextIssue.


AJ ONeal

Tauren Mills

unread,
Jul 21, 2010, 7:30:14 AM7/21/10
to futures-j...@googlegroups.com
AJ,

This is good stuff, thanks! I'd love to see more like this. I've started using FuturesJS and so far haven't had too many problems. Sorry in advance for the large posting, but I would be interested in your insights.

The use case for subscriptions sounds like it might perfectly satisfy one of my needs. However, I feel that there must be other uses for it, but I'm having a hard time figuring out scenarios in my application. Perhaps if I give you some details, you will be able to easily suggest good uses for FuturesJS.

First of all, my ultimate goal is rather grandios, so I'll just do a quick overview of it. I'm attempting to build a component-based infrastructure on top of jquery to meet my needs. There are many MVC-based javascript frameworks out there, but I haven't seen anything purely component-based. In Java-land, I prefer the Wicket framework, and am attempting to see if something similar can be done in Javascript-land for single-page applications utilizing RESTful services and JSON data. 

If someone reading this message does't know the difference between component-based and MVC frameworks, this post gives a decent overview:

 The following is a rough initial stab at a design and may change drastically.

1. Components are self-contained objects that contain all of the logic required to render themselves. 
2. A component can be inserted into any location in the DOM. 
3. Multiple instances of a Component can be created and inserted into the DOM in multiple locations.
4. A component keeps a reference to a pre-compiled template used to render itself
5. A component has a Model that references data in a DataProvider object. The data in the Model is used to render the Component. 
6. A DataProvider object knows how to retrieve data from a JSON-based service and/or local HTML5 storage, etc.
7. Components listen for changes in their data Model and automatically refresh the UI when the data changes (only the specific component who's data has changed, not the full page)
8. Multiple instances of a component, or even different types of components can reference the same data in a DataProvider. Thus a single property change will automatically update in all places it is displayed in the UI.
9. Components can contain other components, which can contain components, etc.
10. Components might get used inside of many other components, encouraging code reuse

The goal is to encapsulate logic into small, self-contained, testable components. Once components are created, an application built on this infrastructure should only need to perform CRUD actions on the DataProvider, and all server communication and UI updating will automatically be handled. This should significantly simplify event handler code.

If you understand what I've described above, what features of FuturesJS do you see me utilizing? Any specific suggestions you can provide? Currently, I've experimented with FuturesJS sequences, promises, and joins. For the most part, it seems to be working well.

SEQUENCES
--------------------

Initially, my single-page application loads from an HTML file with included javascript files. When the document is ready, I initiate a sequence to do the following:

1. Load a JSON document via AJAX that describes the current state of the application UI for the logged in user. For instance, what is the organization of their dashboard widgets, what tabs have they created, which tab is selected, etc. This describes which types of Components are used and where they are placed.
2. Based on the UI description just loaded, one or more container files are loaded via AJAX. A container file is a self contained file that contains both HTML template markup and javascript code to fully describe one or more related Components. All of the container files necessary to provide the components used in the UI are loaded.
3. Component instances are created and rendered based on the UI description.

A simplified version of the code looks like this:

Futures.sequence(function (callback) { 
// Load UI description for user
App.loadUI(callback);
})
.then(function(callback, prevResult, index, results) {
// Load all containers specified in UI description
App.loadContainers(callback);
})
.then(function(callback, prevResult, index, results) {
// Build and render UI
App.buildUI();
});

Is this the proper way to use subscriptions? Anything you can recommend? I'm not really using return values at this time, instead keeping track of data in my App object, but may explore that more.

PROMISES and JOINS
---------------------------------

As an example, inside of App.loadContainers, I use both promises and joins.  Simplified, it looks like this:

App.loadContainers = function(onLoaded) {
var promises = [];

// Loop through containerNames array (populated by loadUI)
$.each(containerNames, function(i,name) {
if (containers[name]) {
// Container already loaded
return;
}

promises[i] = Futures.promise();

var $container = $("<div>");

// Add this container to temporary markup cache
// until markup is compiled into template functions
containerMarkup.append($container);

// Load a container
$container.load(containerPath+"/"+name, function(response, status, xhr) {
if (status === "error") {
log.debug("Error loading container "+name);
// Return without exectuing onLoaded callback
return;
}
log.debug("Container " + name + " loaded successfully.");
// Add this container to the App's containers array
containers[name] = $container;
promises[i].fulfill();
});
});

Futures.join(promises)
.when(function(p_arr){
log.debug("ALL CONTAINERS LOADED");
if (typeof onLoaded === "function") {
onLoaded();
}
})
.fail(function(p_arr) {
log.debug("ERROR LOADING CONTAINERS");
});

Using an array of promises and a join in this manner seems to work well until one of the container files specified doesn't exist. The join.when never runs (which it shouldn't), but fail() never runs either. Is there a way to get fail() to run? How do I set a timeout?

Ideally, my application should continue to function, even if a container file didn't load. I'd like to retry the loading in case there was just a network error. If the file still doesn't load, the UI should still be built and rendered, but any Components that haven't been defined would have a default component used instead and would display an error icon and/or a message indicating that the component couldn't be located.

Am I properly using promises and joins here? Is there a better approach to this?

Thanks again, I'm excited to learn more about FuturesJS and utilize it in my projects.

Tauren

AJ ONeal

unread,
Jul 21, 2010, 11:13:34 AM7/21/10
to futures-j...@googlegroups.com
Tauren,

This is exciting! Over the past year or so I've been investigating a lot [2] of what's going on in computer science (Google Tech Talks, Yahoo Theatre, FOSS discussions on Vimeo / YouTube, etc).

About 4 months ago I came to the conclusion that JavaScript (and event-driven programming) needed a different kind of framework than anything I could find.

Over the next little while I came up with a bunch of ideas [3] and started to work on TriforceJS. The interesting thing is that it (what I had in my head) is exactly what you're describing with a component-based framework. I even pitched the idea to a few people at a local user-group and got some positive feedback, but no one seemed to have heard of that kind of model before.

I searched out the best libraries I could find [1] and started working on Triforce, but I found that I didn't have things thought out clearly enough and I was still missing some of the pieces - the most important one being an easy way to handle asynchronous programming.

I'll get back to you later with some more material and fix that bug with the join not firing the fail event as it should.


AJ ONeal

[1] Good Ideas
jQuery - DOM
Sammy / jQuery BBQ - State
PURE - Template Rendering
jStore - HTML5 / Flash / other local storage abstraction
jQuery.delegate / JavaScriptMVC - controller logic
SproutCore - data binding (though I later thought that I might not need data-binding)
DamnIT - error reporting

[1.1] Maybe not as good ideas
OpenAJAX - a module hub

[2] Research
The Lazy Programmer's Guide to Secure Computing

[3] Musings

Tauren Mills

unread,
Jul 21, 2010, 4:28:00 PM7/21/10
to futures-j...@googlegroups.com
AJ,

I'm glad this excites you, as it totally excites me too. I've come across most of the resources you listed and will review the other ones as well. It sounds like we very well might be heading down the same path and perhaps some collaboration is in order. I seem to keep writing novels, so I apologize in advance for the size of this message.

I really like the ideas behind PURE as well. Are you familiar with the Apache Wicket framework at all? It provides the cleanest separation between markup and logic of any server-side web framework that I've seen. Each component in Wicket has a Java file and an HTML file, with zero code in the HTML file. Components can sub-class other components, and HTML is inherited and/or extended as well. From the separation of code from presentation perspective, it is very similar to the way PURE works. Even if you are not a Java programmer, I highly recommend that you at least look into it a little, because it has some great concepts that I think could be utilized client-side.

For templating, I want something similar to PURE, with no looping logic or if/then logic necessary in the template. Mustache claims no templating logic, but although I haven't really looked into it much, the examples seem too heavy to me. Although PURE's ideas are great, in practice I'm not so sure that PURE is really the best way to go. 

So I'm currently using an implementation of Microsoft's jQuery Templating proposal. The entire proposal is a must read, but in particular, see the section Expressionless Templates. This makes it easy to add behavior and jQuery features (click handlers, plugins, etc.) to elements in a template. The great thing about this, is now I can use a combination of styles, both PURE-like with Expressionless Templates, and Resig micro-template-like with {%= customer.name.first %} in-template markup as well. And these templates are pre-compiled into functions, so they run fast!
http://github.com/nje/jquery-tmpl  (note this code is newer than the version I'm currently using)

John Resig responded to this proposal with his own suggestions. He has some good ideas as well, but the Expressionless expressions are missing, which I think is a big problem. And his still requires looping/if/then logic to be embedded in the template.

In my opinion, none of these are perfect yet. But some combination of features from PURE and the two jquery proposals would be.

There is also a proposal on data-binding. I haven't dug into it too deeply, but I wasn't impressed initially. It seems to rely too heavily on explicit linking, where you link a form input field to a property in an object. I'm looking more for a way that a component will auto refresh itself if its underlying data model is updated. And it should be smart -- a component need not get refreshed if one of it's subcomponents was refreshed due to the data change. Lastly, the same data object can be used by multiple components, so any place that data is displayed should automatically get updated with one quick change to the data model.

Other data-binding projects include chain.js, which has some interesting ideas. I'm not sure how much of it could be used, but it is worth looking at.

Other interesting resources:
http://www.bennadel.com/projects/cormvc-jquery-framework.htm (MVC-based, but pretty well thought out, and easy to try out)

I'm also closely watching Google Closure Library. I'd really like to at least integrate Google Closure Compiler into my build process.

The problem for me is that my work is focused on delivering version 3 of a real-life application in a very short time frame. In order to meet my customer-driven needs, I'm having to intelligently cut some corners. For instance, I'm leaving data binding out for now, but trying to build a base foundation that will allow me to add it later. I don't really have any of the framework that I describe separated out from my application yet, so it will be hard for me to share code at the moment. But I'd like to collaborate, so maybe we can find some way to do so.

Thanks again for your interest.

Tauren


Reply all
Reply to author
Forward
0 new messages