Promises.
Instead of callbacks for the event listeners, it would be incredibly useful to be able to promisify them. Bluebird's promisifyAll doesnt work because the callbacks are not nodeback style. Is this something on the roadmap for the future?
what would it look like? Not Bluebird's promisifyAll? could you create a small/medium snippet of lib/irc.js as an example? as far as I'm aware we'd like to avoid dependencies to remain 'vanilla' nodejs as possible, but if it helps with error handling I'd personally consider it, not sure about others/contributors though. Right now I believe the focus should be PR merging. #423
For example, Id like to be able to do this:
var irc = require('irc');
var winston = require('winston');
var client = new irc.Client('irc.yourserver.com', 'myNick', {
channels: ['#channel'],
});
client.connectAsync()
.then(function(){
client.addListenerAsync('message#').then(function (from, to, message) {
// ... handle message
}).catch(function(err){
winston.error(err);
client.say(nick, 'Error trying to handle your message.');
});
})
.catch(function(err){
winston.error(err);
throw err;
});
Being able to use async calls lets us chain promises and better catch errors that bubble up in the code. It gives us the ability to use the full power of bluebird and to properly make the code asynchronous.
Well, i think small steps first, i do think this would be the right direction, but I'm not sure a es6 promises transformation would be an immediate benefit. I've been reading about some problems and they may not be mature enough, native nodejs and bluebird included, leaking to the failure call and making it indistinguishable between a process crash and an error that can be normally handled, it seems people tend to still be using a try-catch in the failure, which would be redundant imho. How many more extra lines would be added to support promises?
So, a few things...
Events
Promises do not replace events, they replace 'nodebacks' (Node.js callbacks). Promises only reject or resolve exactly once, whereas events occur zero or more times. They're both useful for different purposes.
client.on("message") is something you'd use events for, whereas client.getUserList("#channel") would be something you'd use promises for.
Error handling
ES6 promises unfortunately don't have as robust error handling as Bluebird does. Bluebird, however, has very good error handling:
- The
.catchmethod allows specifying a 'filter' or 'predicate' for errors. This eliminates the "forgot to rethrow" scenario. - Propagation is automatic. This is far, far more reliable than nodebacks, where it is almost inevitable that you're going to miss an error somewhere.
- You cannot both reject and resolve a promise. This prevents the common nodeback scenario of forgetting a
returnin your error handling, and accidentally calling your callback twice - once with an error, once with a success value. - Bluebird emits an
uncaughtRejectionevent on theprocessobject. This allows you to log uncaught errors and forcibly exit your process (process.exit(1)), thereby providing similar error handling to synchronous errors.
There exists no problem in 'distinguishing between a process crash and an error that can be normally handled'. Promises (when used correctly, eg. using Promise.try in Bluebird) ensure that all errors, whether synchronous or asynchronous, end up in the same 'pipeline' and can be handled in the same way.
What errors should be handled, depends entirely on your application. This is not any different with promises - they simply ensure that you can handle all errors in a logical place.
More info
Promises really aren't an optional thing where it concerns single-async-result methods - it is humanly impossible to write any real amount of correctly functioning asynchronous code in Javascript using nodebacks. There are too many open failure cases.
More about error handling here, more about Bluebird here.
EDIT: To clarify, ES6 promises have the "double callback prevention" and the automatic propagation, but not the error filtering nor the uncaughtRejection event. I would strongly recommend using Bluebird rather than ES6 promises.
:+1: Promises are in the language, you can't avoid using them in 2015.
@joepie91 thanks for the infos!
@step1step2 Just because the new Telsa comes out doesn't mean you can't still drive a Beatle. :) but it would be cool to see bluebird promises implemented, but being bedazzled for a limited salable project might be overkill.
As far as i know, there won't be any planes to run multiple bots in a single instance, so the efficiency need only be minimal. Providing the ability for other developers to scale in a forked project would be something to consider though.
While I do enjoy me some promises, and have had the same thought as @step1step2, I don't think we should replace the events with promises, for the reason @joepie91 states.
Could we benefit of some functions returning a promise instead? Certainly. But before we need to:
- a) check what we gain vs the work we have to do
- b) check the rewards of said gain vs the rewards of the previous implementation
- c) implement it by step [because this is time-consuming AF]
In the end: Would we gain much, much, much more than we already have or are we doing it "because its cool and it will shine"?
If there is, indeed, a noticeable gain (which I doubt, mind you) then I'm all for it. Otherwise it's "just nice to have" and therefore could be a MR done by @step1step2 him/erself subject to the normal PR methodology.
Events are different then promises. A promise should never get called more then once. What you are asking for is a fluent api not promises.
Events are different then promises. A promise should never get called more then once. What you are asking for is a fluent api not promises.
Never knew this existed and I can get behind this one :) (also, TIL)
What promises would be good for is things like whois.
const who = await client.whoIs("SirCmpwn");