Let's say you're communicating with a GUI over the network: that's
cool, sometimes it's necessary. I recommend writing a wrapper that
abstracts all that asynchronous business into a set of commands that
can be queued up and run, since it's only the last callback you're
really interested in.
> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>
>
browser
.chain
.session()
.open('/')
.assertTitle('Something')
.and(login('foo', 'bar'))
.assertTitle('Foobar')
.and(login('someone', 'else'))
.assertTitle('Someone else')
.end(function(err){
if (err) throw err;
});
The language includes named function declarations. Use them. That
alone would make your example way less terrible.
--i
Cut out the "var" and the "=". But yeah, "function" is long and
klunky for how common it is. I'd love a shorter keyword for it.
Here's a very brief untested example of what I'm talking about:
https://gist.github.com/775591
I usually only care about success or failure, so I don't use any kind
of "passalong" util in my programs. But it's not hard to see how this
general technique could be applied in other ways.
--i
IMO this is a great example; especially for new comers. It makes the
strange looking yet common function nesting look more familiar, then
progresses to show the awesomeness of JS in a simple, clear and
understandable way.
Sometimes i think those who are intimately familiar with the nested
callbacks/anon function style may not realize the amount of angst and
confusion it can cause for the uninitiated.
- shaun
get_val("foo", function(error, foo){
if (error) print("there was an error");
else get_val("bar", function(error, bar){
if (error) print("there was an error");
else get_val("baz", function(error, baz){
if (error) print("there was an error");
else print(foo + bar + baz);
});
});
});
Sync:
try {
print(get_val("foo") + get_val("bar") + get_val("baz"));
} catch(error) {
print("there was an error");
}
The sync version is cleaner: you can see at a glance what it does. It
prints something -- the sum of 3 values returned by get_val. In case
of an error, you get "there was an error". You get the luxury of
handling the error in a single place.
The async looks like the low-level version of the sync one. If we
could disassemble a JavaScript function, it would look pretty much
like the async version (in terms of program flow). What happens is
that get_val("foo") is executed first, then get_val("bar"), then
get_val("baz"), then their sum is computed and printed -- that's
exactly what both versions do. But which one do you prefer to write?
I don't want to hurt anyone's feelings, but to me at least, Node is
unusable for serious work because of this. I'm prepared to lobby
against do-everything-asynchronously for a long time. :-)
Cheers,
-Mihai
--
Mihai Bazon,
http://mihai.bazon.net/blog
print(a,b,c)
There are many of those. Have fun. (Not being facetious.
Programmers write better programs while enjoying the process, so if
that means using Rhino or v8cgi or Ruby, more power to you.)
This conversation is a bit silly. I mean, conceptually, asynchronous
code *is* a bit more complicated.
For many problems, threads do not scale effectively. But for many
problems, they're perfectly adequate, and if you're using an
implementation that's well understood, you may even be able to work
around the Hard Problems that they introduce.
Node is cool and hot and all the tech blorgs in the blagodome are
weblooging about how awesome and fast and super insanely stupid sexy
it is. But that doesn't mean it's best for every problem, or that
JavaScript is everyone's favorite language, or that you have to love
callbacks, or that you should use it.
When you're writing network programs, your program is a proxy the vast
majority of the time. It is a glue that wires together a few
different things that *by their very nature* are most efficiently
handled with asynchronous evented message-passing. XMPP, HTTP, AMQP,
child processes, etc. Those problems are well served by an event
loop.
You can run an event loop in C. You know what? After juggling
structs and function pointers for a bit, all this "verbose" JavaScript
starts to look pretty nice.
> for many "normal" CRUD type apps where blocking isn't that much an issue...
Are you joking? That's *exactly* the sort of app where blocking very
quickly becomes a *huge* issue.
Or do you mean the kind of app where only one user is ever going to be
creating, reading, updating, and deleting data at once? Because
that's what blocking IO means.
All websites are fast with one user on localhost.
> On 01/12/2011 06:54 PM, Preston Guillory wrote:
>> Sam has a point. Asynchronous code is much larger and has a lot of
>> syntactic noise. Look at his example: synchronous Java does in 2 lines what
>> takes 7 lines of asynch code
Except that the 7 lines of async code *can handle other events while
waiting*, without the overhead of coroutines or threads.
And, with the Java version, there's a *ton* of stuff going on below
the surface. Actually doing real work in a higher-level-than-c
language with an event loop is kind of a newish thing. Granted, those
of us who cut our teeth on web browsers have been doing it forever,
which is part of why JS is so right for this task. But the tooling is
not super mature, and node is a lowlevel library by design.
>> Named intermediate functions
>> don't help -- see how Isaac's example stretched to 14 lines.
They reduce indentation, label blocks, and improve stack traces. They
won't improve your golf game.
>> But for a lot of common programming tasks, Node.js
>> is verbose, for sure.
The advantages are that you can do a bunch of things in parallel, and
handle "local" stuff in the pattern as "remote" stuff.
I write most of my shell scripts in Bash.
On Wed, Jan 12, 2011 at 23:39, Sam McCall <sam.m...@gmail.com> wrote:
> Plate(mainWindow).menu('File').openMenu().item('Open').click().end(function(err)
> {
> if(err) throw err;
> });
>
> Where all the library functions are still written in callback-as-last-
> parameter style.
See? I *told you* you could do better than my example ;D
If you can come up with a terser way to express callbacks, that
doesn't lose anything in translation, then by all means, implement it.
I think that this problem, such as it is, will be solved by either
writing a new language no one uses, or just sucking it up and using
the JavaScript we have instead of the JavaScript we wish we had.
--i