7 ms·
It's really awkward to write evened code without a good implementation of futures ( or go's channels ). The problem is that you end up nesting a lot. Look at th
by xal 17y ago
It's really awkward to write evened code without a good implementation of futures ( or go's channels ). The problem is that you end up nesting a lot. Look at the example for the posix rename here: http://nodejs.org/api.html#_posix_module http://nodejs.org/api.html#_posix_module
Now imagine implementing a normal http controller. You have to do say 5 MySQL call (or redis, whatever) to get all the data you want. This means that you have to nest together 5 closures. Now if any of the methods fails and there is no global error handler that disconnects the client then that means that the connection will hang forever until the browser user hits the stop button. Spotting these situations becomes really hard with complex code.
Futures ( Go channels ) solve this because they block the thread when someone accesses the data. If you want to do 3 db calls you can just write familiar code:
var a = db.select(...);
var b = db.select(...);
var c = db.select(...);
print c #=> blocks until c has returned
- Tichy 17y ago"The problem is that you end up nesting a lot." I haven't done that much of asynchronous programming, but I think you end up creating some helper constructs that help prevent excessive nesting. For example you could create a function that takes an array of functions and calls them sequentially (in the sense that when the first callback is executed, it calls the second function and so on).
- swannodette 17y agoYou can't get around nesting if functions take a callback in their interface. It's viral. You can mitigate _some_ of these problems by defining a custom event system, but this makes code logic very hard to follow. It's better in a complex system to hide the mechanism altogether. A little higher on the thread I point out that this can be done by custom events and function decoration.
- tolmasky 17y agoThis is precisely my concern, and I have talked to a lot of people regarding this exact point. I think node.js is really cool but I would love if this was just built into the language, such that code would perform asynchronously but not move to the next line. var a = something_async(), b = something_else_async(); Upon calling something_async, the code starts waiting and blocks further execution until it is ready, going to the next statement. This is not a foreign concept at all, and is used in javascript as well with alert, prompt, confirm: fries = window.confirm("Do you want fries with that?") confirm is an async method (has to wait for the user), but the next line is not executed until it returns. I personally see no advantage to creating a system of callbacks: do_x(function () { do_y(function() { do_z() }) }) when this would be much more readable: do_x(); do_y(); do_z(); and would have the exact same perf characteristics. In fact, you could probably simpy code transform the latter into the former (I know this is what stratified JS does), although this is probably the worst way to do it. What you really want is to just auto-call "wait" on every promise (I believe wait still gives you the asynchronous benefits). Of course, the main "drawback" to this is that you need language support to pull it off, so you need to implement a preprocessor of some sort.
- _sh 17y agoI don't understand your concern. When you say 'Upon calling something_async, the code starts waiting and blocks further execution until it is ready', you're describing a synchronous call. Indeed window.confirm is a synchronous function--nothing is executed until it returns. And yes, both asynchronous and synchronous operations have their place, umm, except perhaps in Haskell where things get funky. Chaining async operations together in javascript can be tedious, but its easy enough to write a helper function to handle it for you. Every javascript app I've written that uses AJAX always has some form of createCallback(context, function, arguments) function.
- xal 17y agoRe-read my example. All 3 db queries are run in parallel however the code does not continue if you access one of the values until the value is available. In a typical web application you usually get 3-5 things from the db, then you start rendering the templates. Each DB query waits for completion, then it starts the next which is a huge waste of time. In fact the system can easily start the parser and template renderer while the DB queries run and all the data will likely be available once it's accessed. This means you have all the benefits of synchronous processing with the majority of the advantages of async. The vast majority of web applications would likely very rarely block a thread in such an architecture. I'm very surprised that not more languages implement this pattern. Maybe i'm missing something but this is the major feature of GO, except that almost everyone missed it and focused on the fact that it compiles fast and looks like c
- Hexstream 17y agoSeems like you the dataflow paradigm is exactly what you'd need. With dataflow, trying to read a variable that doesn't know its value yet blocks until the value becomes known.
- swannodette 17y agoYou don't need language support and you don't even need a preprocessor. You just need to define a custom event system. do_x(); do_y(); do_z(); Ideally those three should not even be dependent on each other (FP to the rescue). They should absolutely not block if you're going to write your code this way. If they are dependent and need to block they should be written this way: do_z(do_y(do_x())); Each one delivers a promise for it's computation. All you need is custom events and function decorators. Port my library Promises.js to Node.js ;) It's only about 300 LOC (another 5 or so to implement function decoration). http://github.com/ShiftSpace/promises http://github.com/ShiftSpace/promises