Asynchronous Method Queueing at Last via `Futures.anywhereify()`!

3 views
Skip to first unread message

AJ ONeal

unread,
Aug 4, 2010, 10:29:43 AM8/4/10
to futures-j...@googlegroups.com
I'd like suggestions for a better name for the method. `anywhereify()` is perhaps to lame...

The way it works is that you pass in data providers and data consumers.

Providers must be promisable.
Consumers may be promisable, or not (they will be automatically `asyncify()`d), but they must return the data.

var Contacts = Futures.anywhereify({
  // Providers must be promisables
  all: function(params) {
    var p = Futures.promise();
    $.ajaxSetup({ error: p.smash });
    $.getJSON('http://graph.facebook.com/me/friends', params, p.fulfill);
    $.ajaxSetup({ error: undefined });
    return p.passable();
  },
  one: function(id, params) {
    var p = Futures.promise();
    $.ajaxSetup({ error: p.smash });
    $.getJSON('http://graph.facebook.com/' + id, params, p.fulfill);
    $.ajaxSetup({ error: undefined });
    return p.passable();
  }
},{
  // Consumers will be called in synchronous order
  // with the `lastResult` of the previous provider or consumer.
  // They should return either lastResult or a promise
  randomize: function(data, params) {
    data.sort(function(){ return Math.round(Math.random())-0.5); // Underscore.js
    return Futures.promise(data);
  },
  limit: function(data, n, params) {
    data = data.first(n);
    return Futures.promise(data);
  },
  display: function(data, params) {
    $('#friend-area').render(directive, data); // jQuery+PURE
    // always return the data, even if you don't modify it!
    // otherwise your results could be unexpected
    return Futures.promise(data);
  }
}, context, params);

Contacts.all(params).randomize().limit(10).display();

I'd like to point out that I had this idea several months before I had heard of Twitter's Anywhere API, but if I can't think of anything else to call it, riding on their success doesn't bother me... too much...

AJ ONeal

Tauren Mills

unread,
Aug 4, 2010, 2:07:41 PM8/4/10
to futures-j...@googlegroups.com
AJ,

Great work! Can't wait to try it out.

I don't think the primary intent of the @Anywhere API is for method chaining, so anywhereify() probably isn't the best name. I'm not thrilled with the name Anywhere even for twitter. I can understand the desire to piggyback on their success, but perhaps something like chainify() would be better? 

Here's a good explanation of @Anywhere's purpose:

A few questions:

1. What are the arguments 'context' and 'params' on the anywhereify() method? The first two arguments are for providers and subscribers, but what do the other two do?

2. What is in the params argument in the subscribers functions? It isn't used in randomize(), limit(), or display().

3. Is there any kind of data caching is going on behind the scenes? Can I call just a subscriber function later on without first doing a provider function?  For instance:
Contacts.all(params).randomize().limit(10).display();
// much later... 
Contacts.randomize().limit(20).display();
4. If I do the above, would I be randomizing just the 10 data items that were the result of the first command, so my output would still be 10 items, just in a different order? Or do I still have access to all the data, and would get an output of 20 random items from the original all() call? Or must I first call a provider function before a subscriber function? Perhaps there should be a jquery-like end() method to set a chain back to the original state?

5. Is the point of modifying $.ajaxSetup() so that you can have an error handler with $.getJSON commands? Since $.ajaxSetup is a global setting, couldn't that cause conflicts if multiple async events are going on at the same time?

Tauren


--
Please use prefixes: [Pony] Feature requests, [TestCase] Test cases, [Bug] if you're lazy. If you have contract work or position for FuturesJS devs, prefix [Bounty] or [Job].
-----
To post to this group, send email to futures-j...@googlegroups.com
To unsubscribe from this group, send email to
futures-javascr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/futures-javascript?hl=en

AJ ONeal

unread,
Aug 4, 2010, 9:49:31 PM8/4/10
to futures-j...@googlegroups.com
Correction: Asynchronous Method Queueing at Last via `Futures.chainify()`!

1. What are the arguments 'context' and 'params' on the anywhereify() method? The first two arguments are for providers and subscribers, but what do the other two do?

`context` is the `this` to be used.

`params` is reserved for future use.
My goal is to have only the most basic arguments enumerated and to put all of the kitchen sink stuff that I might mishappenly add in the params.

 
2. What is in the params argument in the subscribers functions? It isn't used in randomize(), limit(), or display().

Just an example to show that you can pass in any sort of params that you would like.
`data` must be the first argument to any consumer when defined, but all other arguments will also be `apply()`d when called
 

3. Is there any kind of data caching is going on behind the scenes? Can I call just a subscriber function later on without first doing a provider function?  For instance:
Contacts.all(params).randomize().limit(10).display(
); // much later...
Contacts.randomize().limit(20).display();

No, but caching is part of TriforceJS. In Triforce all(), one(), some(), etc will be cached (on a per-id basis) with parameters to specify time_to_live for `stale` (when it should return from the data cache, but prefetch for the next call) and `useless` (the data from the cache should be discarded and will not return until fresh data is available).

I don't want Futures to handle Models. I want to keep it down to just async tools.
 
4. If I do the above, would I be randomizing just the 10 data items that were the result of the first command, so my output would still be 10 items, just in a different order? Or do I still have access to all the data, and would get an output of 20 random items from the original all() call? Or must I first call a provider function before a subscriber function? Perhaps there should be a jquery-like end() method to set a chain back to the original state?

This is something that I'll consider while developing Triforce. I think this would be better than `.end()` since we're not nesting models:
var queue = Contacts.all(params).randomize().limit(10).display();
// much later...
queue.randomize().limit(20).display();

The way Triforce will handle nested Models is by creating Composite models on the top level.

 
5. Is the point of modifying $.ajaxSetup() so that you can have an error handler with $.getJSON commands? Since $.ajaxSetup is a global setting, couldn't that cause conflicts if multiple async events are going on at the same time?

In JavaScript there is only 1 thing ever going on at a time. The call stack must return before the next event loop occurs - at which time the next callback or setTimeout or setInterval, or User event in the stack is called. Since I'm setting the error handler back to `undefined` before the function returns, this is a non-issue.
 
AJ ONeal

Tauren Mills

unread,
Aug 5, 2010, 1:21:36 AM8/5/10
to futures-j...@googlegroups.com
AJ,

Thanks for the answers.
 
5. Is the point of modifying $.ajaxSetup() so that you can have an error handler with $.getJSON commands? Since $.ajaxSetup is a global setting, couldn't that cause conflicts if multiple async events are going on at the same time?

In JavaScript there is only 1 thing ever going on at a time. The call stack must return before the next event loop occurs - at which time the next callback or setTimeout or setInterval, or User event in the stack is called. Since I'm setting the error handler back to `undefined` before the function returns, this is a non-issue.

True, at least for now in web browsers. But I'm unclear if that will continue to be the case with web-workers on the horizon. Also, I was thinking more along the lines of if anywhereify() was used server-side, such as in node.js or something. I thought I read that Rhino supports multithreaded javascript, but I could be mistaken. And there is a comment on the nodejs site that says this:

In future versions, Node will be able to fork new processes (using the Web Workers API ) which fits well into the current design.

I guess this is a moot point since I probably wouldn't be using jquery server-side anyway. And I realize your use of $.ajaxSetup() isn't part of Futures either, just example client code. I just hadn't seen it used that way before and it raised some concern. Such as if an error handler had been set previously, the original handler would be lost. But no worries, your point is made, and I could always work around that or just use $.ajax() directly instead of $.getJSON().

You mention Triforce several times. Is there a place to discuss it? Any useable code yet? Are you still intending to make it function in an MVC-style manner, or are you considering a more component-based approach? 

Thanks,
Tauren

Reply all
Reply to author
Forward
0 new messages