Just by seeing what I've wrote now, I can see that one is much smaller, so in terms of code golf Option 2
is the better bet, but as far as which is cleaner, I prefer Option 1
. I would really love the community's input on this.
Option 1
something_async({
success: function(data) {
console.log(data);
},
error: function(error) {
console.log(error);
}
});
Option 2
something_async(function(error,data){
if(error){
console.log(error);
}else{
console.log(data);
}
});
In all honesty, I prefer to take them one step further, into Promises/Futures/Deferreds/etc... Or (/and) go into a "custom event" queue, using a Moderator (or an observer/sub-pub, if there is good reason for one particular object to be the source for data).
This isn't a 100% percent of the time thing. Sometimes, you just need a single callback. However, if you have multiple views which need to react to a change (in model data, or to visualize user-interaction), then a single callback with a bunch of hard-coded results isn't appropriate.
Things are now much less dependent upon one big callback and you can mix and match and reuse code.
If you want to hide the moderator, you can make it a part of your objects:
If this looks a little familiar, it's similar behaviour to, say Backbone.js (except that they
extend()
the behaviour onto objects, and others will bind, where my example has simplified wrappers to show what's going on).Promises would be the other big-win for usability, maintainable and easy to read code (as long as people know what a "promise" is -- basically it passes around an object which has the callback subscriptions).
Or var blog_comments = [ /* ... */ ],
All of the cruft there is to show how powerful promises can be.
Look at the
.forEach
call there. I'm using Image loading instead of AJAX, because it might seem a little more obvious in this case:I can load hundreds of blog comments, if the same user makes multiple posts, the image is cached, and if not, I don't have to wait for images to load, or write nested callbacks. Images load in any order, but still appear in the right spots.
This is 100% applicable to AJAX calls, as well.
They are not exactly the same. Option 2 will still log the (data), whereas Option 1 will only log data on success. (Edit: At least it was that way before you changed the code)
That said, Option 1 is more readable. Programming is not / should not be a competition to see who can write the fewest lines that do the most things. The goal should always be to create maintainable, extendable (if necessary) code --- in my humble opinion.
Promises
have proven to be the way to go as far as async and libraries likebluebird
embrace node-style callbacks (using the(err, value)
signature). So it seems beneficial to utilize node-style callbacks.But the examples in the question can be easily be converted into either format with the functions below. (untested)
Many people will find option#1 easier to read and to maintain - two different callback functions for two different purposes. It is commonly used by all Promise Libraries, where two arguments will be passed. Of course, the question Multiple arguments vs. options object is independent from that (while the object is useful in
jQuery.ajax
, it doesn't make sense forpromise.then
).However, option#2 is Node.js convention (see also NodeGuide) and used in many libraries that are influenced by it, for example famous async.js. However, this convention is discussable, top google results I found are WekeRoad: NodeJS Callback Conventions and Stackoverflow: What is the suggested callback style for Node.js libraries?.
The reason for the single callback function with an error argument is that it always reminds the developer to handle errors, which is especially important in serverside applications. Many beginners at clientside ajax functions
don't careforget about error handling for example, asking themselves why the success callback doesn't get invoked. On the other hand, promises withthen
-chaining are based on the optionality of error callbacks, propagating them to the next level - of course it still needs to be catched there.