Concerning Promises and NodeJS history: When I first started lurking in 2010, NodeJS was using promises. At first it sounded cool but I couldn't figure them out and gave up. About a year later I started lurking again and discovered, lo and behold, that promises had been jettisoned. It was a nightmare of complexity. They are extremely opaque and easily breed expressions that are very difficult to figure out "what's really going on." Also there were a bunch of different versions of promises, creating fragmentation.
NodeJS makes pragmatic decisions and always optimizes for community involvement. Dahl originally chose javascript after evaluating a lot of languages because it was designed for simplicity, pragmatism, and these features facilitate community involvement. A simple callback passing style proved to be more in line with Node's core principles. It was more "nodesque" (don't shoot me please :-). Brendan Eich, author of JavaScript, encapsulates pretty well the simplicity and malleable nature of JS: As is well known at this point, I created JavaScript in ten days in May > 1995, under duress and conflicting management imperatives--"make it look > like Java,"make it easy for beginners," "make it control almost everything > in the Netscape browser". Apart from getting two big things right (first-class functions, object > prototypes), my solution to the challenging requirements and crazy-short > schedule was *to make JavaScript extremely malleable from the start.* (Quoted from Foreword to *Effective JavaScript*, page xiii) Arguably, the callback passing style in NodeJS is also optimized for malleability and extensibility. E.g., Bruno Jouhier developed a system called "streamline" that depends on the consistent API callback style to facilitate linear programming without promises. (A separate process compiles the code that uses streamline, which is linear and resembles synchronous code, into callback-oriented javascript.) I think Bruno's doing a thing with ES5 generators now, for the record, but my point is that something like streamline shows that a consistent and simple style reaps long-term extensibility. In summary, as I understand it, JavaScript was chosen for NodeJS because its community and its leaders (thus far Ryan Dahl, Isaac Schlueter, and Timothy Fontaine) preferred the system of asynchronous callbacks. It's fine if you don't like it -- you can use promises or other approaches to make asynchronous programming look like synchronous programming. There's no dogma. However, most people writing an API are probably better off to follow the basic guidelines. Because, generally speaking, if you want other people to use your code, it's best to keep your API as simple, minimal, consistent, and easy to use as possible. In short, if you ask for advice, most seasoned NodeJS developers will recommend that you use the standard callback style for your API. If you google through the NodeJS threads, that is what you'll find advocated by the most prominent members, such as Mikeal Rogers (who commented earlier). Alex On Wednesday, 16 April 2014 06:34:35 UTC-4, willem dhaeseleer wrote: > That fact that node core api's only support callbacks doesn't make them > holy. I understand they used callbacks back in 2009 before > the proliferation of asynchronous control flow in javascript and the state > of promises in V8 / ECMAScript . But today promises are in V8 and wildly > used and you just can't argue with increase in readability, maintenance and > productivity. > I'm sure we could have a lengthy discussion about what makes a good api, > but I think most people will agree with me that consistency should be key. > Providing both promises and callbacks in your api seems like a very bad way > to go. > > The node core API also doesn't really define a *standard*, it defines an > interface, I believe there are even some methods in the api that don't even > respect the *callback(err, > result)*<http://nodejs.org/api/fs.html#fs_fs_exists_path_callback> format. > > The standard is ECMAScript, and ECMAScript 6 has promises, and generators, > use them where applicable. > > > > > > > > On 16 April 2014 12:02, greelgorke <[email protected] <javascript:>>wrote: > >> my only concern about your post is that you simply ignore the standards >> in node. node core apis are callback based, your 3rd party libs should >> honor this. a good api doesn't care much about personal opinions and a) >> supports the standard and b) provides optional methods for convinience. >> >> it's not about whats better. its about what a good api >> >> Am Mittwoch, 16. April 2014 10:27:18 UTC+2 schrieb willem dhaeseleer: >> >>> >>> Hey greelgorke, >>> >>> Great to get some feedback on my answer, I'll try to clarify my >>> arguments some more here: >>> >>> - It always you to pass on asynchronous operations >>>> >>> huh? >>> >>> // foo returns promise >>> var futureBar = foo(); >>> >>> // you can know pass around futureBar to some other api or use it for >>> later reference >>> // with callbacks you will have to write your own wrapper code to get >>> this type of "asynchronous encapsulation" >>> >>> - How many types have you typed *if (err) throw err *or *if (err) >>>> console.warn(err) ?* >>>> >>> you actually type this yourself? >>> >>> Off course not, but i have seen it in to much code already. >>> Obviously i forgot* if (err) return callback(err);* >>> If haven't written in this style anymore for a long time. >>> >>> - Improved readability trough more logical control flow >>>> >>> duh. readability is subjective. >>> >>> Off course it's subjective, but chronological reading order is something >>> I tend to value in most code. >>> Just my opinion. >>> >>> - Integration with coroutines ( you want this ) >>>> >>> huh? how is that connected? >>> >>> An example should clarify this, this uses bluebird: >>> This is obviously a bad use of a database, but the idea is to >>> demonstrate how promises integrate with coroutines. >>> >>> var getTotalFriendBalance = Promise.coroutine(function* (name) { >>> var user, userFriends, x, totalBalance; >>> user = yield db.getUserByName(name); >>> userFriends = yield db.getFriends(user.id); >>> for (x = 0; x < userFriends.length; x++) { >>> totalBalance += (yield db.getAccountInfo(userFriends[ >>> x].id)).balance; >>> } >>> return totalBalance; >>> }); >>> >>> >>> I challenge you to write this peace of code with only callbacks, I think >>> you will find this syntax is much more intuitive and more pleasant to write. >>> This is only possible because all asynchronous methods here return >>> promises (or thenables) that can be used by the coroutine. >>> >>> I hope this clarifies my personal opinion on why promises are better. >>> >>> >>> >>> >>> On Wednesday, April 16, 2014 9:50:22 AM UTC+2, greelgorke wrote: >>>> >>>> inline >>>> >>>> Am Mittwoch, 16. April 2014 08:46:48 UTC+2 schrieb willem dhaeseleer: >>>>> >>>>> >>>>> Andrew, >>>>> >>>>> For the love of all that is dear to us, Use promises, do not support >>>>> callbacks, don't even think about supporting both. >>>>> There is a reason why promises are becoming part of the standard in >>>>> ECMA 6. >>>>> >>>> >>>> they are there to give you an alternative, not a replacement. Callbacks >>>> are simple for simpler things. they are the core pattern and they are >>>> accepted. every single person new to node, can just use them, as soon she >>>> understood async coding style. >>>> >>>> it is a very bad habbit to only provide promises api. one of the top3 >>>> popular modules on npm is async, which handles callbacks. >>>> >>>> So, stop crying about callbacks, learn them and provide a cb-based >>>> interface. and stop saying us. :P >>>> >>>> >>>>> >>>>> Here are a few of many reasons why to choose promises: >>>>> >>>>> - It prevent deep indentation >>>>> >>>> flatten your code. >>>> >>>>> - It always you to pass on asynchronous operations >>>>> >>>> huh? >>>> >>>>> - Asyncronous callstacks and consistent error handling ( you want this >>>>> ) >>>>> - How many types have you typed *if (err) throw err *or *if (err) >>>>> console.warn(err) ?* >>>>> >>>> you actually type this yourself? >>>> >>>>> - Refactoring in callback styled code is extremely tedious to the >>>>> point where it would be almost reasonable to say it's impossible >>>>> >>>> it always hard to refactor bad written code either with callbacks, >>>> promises or even synchronous code. >>>> >>>>> - Improved readability trough more logical control flow >>>>> >>>> duh. readability is subjective. >>>> >>>>> - Integration with coroutines ( you want this ) >>>>> >>>> huh? how is that connected? >>>> >>>>> >>>>> >>>>> >>>>> On Tuesday, April 15, 2014 6:20:05 AM UTC+2, Andrew de Andrade wrote: >>>>>> >>>>>> So at work we're working on a bunch of node modules that will >>>>>> eventually be published as open-source and I'm in favor of callbacks and >>>>>> two of my co-workers are in favor of promises. We've discussed >>>>>> supporting >>>>>> both API interfaces and I was curious what the general consensus of the >>>>>> community was with respect to supporting both and the best way to name >>>>>> functions and methods to support both. >>>>>> >>>>>> That being said, there are three obvious choices: >>>>>> >>>>>> (a) two function types: (1) synchronous functions; and (2) async >>>>>> functions that return promises but also handle callbacks >>>>>> >>>>>> var value = myFunctionSync(); >>>>>> myFunction(callback); >>>>>> var promise = myFunction(); >>>>>> >>>>>> this approach has a tiny performance overhead (since you have to >>>>>> check if the last argument is a function to determine if you should >>>>>> return >>>>>> a promise or execute that function as the callback) and makes all the >>>>>> functions a little convoluted (unless you make one higher order function >>>>>> that you apply to all your callback functions to support both APIs). >>>>>> Furthermore async, higher order, overloaded functions or variable arity >>>>>> functions become impossible since you can't necessarily assume that the >>>>>> last argument is always the callback. >>>>>> >>>>>> (b) three function types: (1) synchronous functions; (2) async >>>>>> callback functions; and (3) async promise functions >>>>>> >>>>>> var value = myFunctionSync(); >>>>>> myFunction(callback); >>>>>> var promise = myFunctionDeferred(); >>>>>> >>>>>> this is ugly but explicit in terms of what to expect and permits the >>>>>> most flexibility. >>>>>> >>>>>> (c) two function types: (1) synchronous functions; (2) async >>>>>> callback functions; >>>>>> >>>>>> var value = myFunctionSync(); >>>>>> myFunction(callback); >>>>>> >>>>>> and promise support is left up to the user by using a nodeify() >>>>>> method from a promise library. This is my preference, but won't make my >>>>>> co-workers happy. >>>>>> >>>>>> >>>>>> With all this in mind, what's the general consensus of the NodeJS >>>>>> community on this issue? I searched google and the archives and could >>>>>> not >>>>>> find any blog posts or discussions that address this particular issue. >>>>>> What >>>>>> are the pros and cons of each approach? What if any libraries implement >>>>>> options (a) or (b)? etc. >>>>>> >>>>>> >>>>>> -- >> -- >> Job Board: http://jobs.nodejs.org/ >> Posting guidelines: >> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines >> You received this message because you are subscribed to the Google >> Groups "nodejs" group. >> To post to this group, send email to [email protected]<javascript:> >> To unsubscribe from this group, send email to >> [email protected] <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/nodejs?hl=en?hl=en >> >> --- >> You received this message because you are subscribed to a topic in the >> Google Groups "nodejs" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/nodejs/NpZ4WT1eOnw/unsubscribe. >> To unsubscribe from this group and all its topics, send an email to >> [email protected] <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
