Bemi Faison wrote:
> I feel that flow-control is the future of JavaScript, and love that
> you're embracing deferreds.

I don't think I'd go that far.  Flow control will ever be only a
single tool in the toolbox.

> I think folks are beginning to realize
> that you can't trust functions - so constructs must evolve in order to
> control their execution.

I don't understand what you mean by "you can't trust functions."  I
find it surprising because I for one try to use JS in a manner much
more like I'd use a functional language than I would, say, an object-
oriented one.  Functions are to me the basic building blocks of the
language.

> Anyway, your flow function looks concise and elegant.

It's definitely concise, perhaps even elegant.  But the real question
is whether it's powerful enough to be useful.  Next week I'm going to
have a go at including this in a real project, and we'll see if it
works even for the environment it was written for.


> I am still working on that walk-thru - trying to keep it simple - but
> would like to apply Flow to your current project: calling multiple
> asynchronous tasks in any order. I'll go over a few ways you can do
> that with Flow.

Thank you.  It's very interesting.  But please don't let this
conversation delay your writing of public documentation for your
library.  If you post brief pointers here to even incomplete
documentation online, I'm more than willing to look at it there.

> For simple flow-control, Flow provides .go() and .wait() methods.
>
> var ajaxCalls = new Flow({
>   ajax1: function () {
>     var flow = this;
>     flow.wait(); // pause the flow
>     doAjax1({
>       onComplete: function () {
>         flow.go(); // resume the flow
>       }
>     });
>   },
>   [ ... ]
> We can now "go to" any number of states in our Flow...
>
>   Flow(ajaxCalls).go('ajax2', 'ajax1', ..., 'ajaxN');
>   // if ajaxCalls were an instance -> ajaxCalls.go(...);

This really reminds me of QUnit's asynchronous testing mechanism.

> [ ... ]
> Of course, invoking a sequence of asynchronous calls may not make
> sense. In order to choose the next ajax dynamically, we'll parse the
> response and tell Flow where to go next.
>
> var ajaxCalls = new Flow({
>   ajax1: function (arg1, arg2) {
>     var flow = this;
>     flow.wait(); // pause the flow
>     doAjax1({
>       onSuccess: function (rsp) {
>         switch(rsp) {
>           case 'ok' :
>             // go here next, and set new arguments
>             ajaxCalls.ajax2(rsp, arg2, 'Hello World!');
>             break;
>           case 'maybe':
>             // go here next and clear arguments
>             flow.target('/ajax3'); // same as "ajaxCalls.ajax3()"
>             break;
>           case 'noway':
>             // go here next, pass original arguments
>             flow.go('/ajax4');
>             break;
>         }
>       }
>     });
>   },
>   // ... etc.
>
> });

This is what my system cannot do.  I could code for something like
this easily enough, but I can't think of a simple declarative way to
handle this branching unless my code becomes much more intrusive.


> This Flow is less naive because each state must tell our Flow where to
> go - you may not want that level of intelligence baked into your code.

I'm trying to isolate exactly that intelligence in my flow
declaration.  The actual functions it composes shouldn't know anything
about the overall flow.  If they have to right signature (namely that
they accept a single parameter and return another of the same type or
a promise that will resolve to the same type) then they can be
composed by this with any other like functions.  A simple chain would
look like:

    var myFlow = flow({fn: func1, done: {fn:func2, done: func3}});
    when(myFlow(inputVal)).then(
        function(resolvedVal) {/* ... */},
        function(rejectedVal) {/* ... */}
    );

Note that func1, func2, and func3 know nothing about the flows in
which they might participate.  And also note that myFlow has the same
signature so can be used in another flow.

What my code does beyond this simple chain is to allow binary
branching:

    var myFlow = flow({
        fn: func1,
        done: {
            fn: func2,
            done: func3,
            fail: func4
        },
        fail: func5
    });

And again, myFlow has the same signature as the individual composable
functions.

As far as I can tell, any system which would allow arbitrary branching
would be significantly more complex.  This simply depends on the
binary nature of a promise's callback/errback pair.  Anything further
would be much more complicated to use, at least anything I've found so
far.  But I'm still looking.


> I encourage you to play with Flow!

I will definitely look at it.  Good luck,

  -- Scott

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/[email protected]/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/[email protected]/

To unsubscribe from this group, send email to
[email protected]

Reply via email to