Usurps #261
We'll be dropping older nodes around version 6, we currently polyfill promises for version 4, so we got them to use.
We'd need tests along with any PR
A problem with promise based apis is that it is not compatible with the optional callback / error event style approach we've adopted;
// Current api
let port = new SerialPort('/bad-port', {autoOpen: false});
port.on('open', () => console.log('yay the port is open!'))
port.on('error', () => console.log('boo we had an error!'))
port.open(); // no callback
// boo we had an error!
port.open(function(err) { if (err) { console.log("I'm dealing with this error") }});
// I'm dealing with this error
In node 6x+ unhandled promises throw globally, in all nodes unhandled error events throw globally. We're still going to support 4x. This might not be something we need to worry about.
So if also always return a promise or only return a promise when not given a callback, and we don't handle it's rejection some nodes will throw. And if we don't provide a callback and don't handle the error event, then all nodes will throw.
All our functions throw when given bad arguments, there seems to be a consensus around rejecting promises instead.
I think this all means that we'd have to switch wholesale to promises instead of callbacks.
There is an alternative approach which we can take, and that is to do what nodejs core is eventually going to do. Providing functionAsync equivalents that return promises.
https://github.com/nodejs/node/pull/5020
That's probably the way to go.
This isn't on the roadmap for now.
Hi @reconbot , any chance of revisiting this, or accepting PR's for work on this?
Currently we are forced to use Bluebird to promisify the port object, and call port.openAsync etc. This is of course a bit redundant, especially now that Native promises have landed in Node and are pretty much mainstream.
When I rewrote the Node API for Sendgrid, we also introduced promise support while maintaining callbacks for backwards compatibility. I see the issue with not passing a callback and not handling rejected promises, which could trip up apps using callbacks. However, given the speed at which you are releasing major versions with other breaking changes, it's conceivable that a new major version is released that either always expects promises/async to be used.
Alternatively, have you considered a flag that enabled promises globally (or during instantiation of the SerialPort object)?
const port = new SerialPort(port, {
baudRate,
autoOpen: false,
usePromises: true,
});
This could even be the default setting, with optional false value indicating the current style of callbacks only usage.
Thoughts?
The next major version is unfortunate. It fixes some major windows performance issues and changes our binary distribution system. Doing the bump seemed worth it even though there's only potential behavior changes.
As for promises. I started using them for the bindings but one of the goals was to match the node stream api as close as possible. In fact most of the "magic" is in the bindings. I'm doing an exploration of other kinds of streams (whatwg/streams, most) and async iterators. But I doubt we'd switch this project to any of them, but instead share the bindings with other packages. (and probably split them into their own package)
So async methods for node serialport? The convention doesn't exist for node streams but we snuck it into #list().
.set(), .get(), .flush(), .drain(), .update(), .open(), and .close() could return a promise if no callback is provided without issue. .read() and .write() already have useful return values and are stream methods. A .writeAsync() would be trivial but a .readAsync() would be difficult to do and would only work on paused streams. I've tried to write a utility function .readAsync() for use on generic streams a few times..pause() and .resume() are sync and also stream methods, no changes there.It seems that node core is moving towards the .fooAsync() style of promised based callbacks. I think it makes sense to stay in "spec". I want to have more discussion about it but I think it makes sense to accept PRs with async prefixed methods. (We should probably fix .list() and make a .listAsync() too.)
PS I'd _love_ to make a non node-streams version of serialport. And I love async/await, a lot.
Thanks for the detailed comments!
Since I use the .on('data') event instead of .read(), for me the main benefit would arise from making .open() and .close() return promises. If the methods you mentioned in your first bullet point could return promises when no callback is provided that'd be great.
I wouldn't mind if the API is split between callback and non-callback functions, but I think the naming would be misleading. E.g. .open() will still take a callback, and it will not be sync, but it might be implied by the presence of an .openAsync().
So I would prefer the approach where .open() returns a promise when no callback is provided. Can probably leave read, write, pause, resume as they are for now.
And I love async/await, a lot
Amen!
I'm wrong on the fooAsync() in core. They seem to be landing on a module namespace. eg require('serialport/promise') but I'm not 100% on that.
I see, interesting read. I guess their main concern is maintaining backwards compatibility with callbacks. It also looks like the discussion ended about a year ago.
For me it's not backwards compatibility it's principal of least surprise. I'd like node serialport to work like everything else does.
Someone needs to be the trend setter ;)
Everything in NodeJs is moving to promises, so I think that a new major release non-backward compatible is acceptable.
I'm 💯 of a different mind these days about this. We still support node 6 which doesn't have async functions but I'd be willing to transpile to ignore that fact.
Nodejs 6 has a scheduled eol date at April 19.
So, it could be the right moment to switch to node 8 updating the code.
Yes, with babel the "compilation" is very easy.
If you need beta testers when you want to update the code with promises/asyncawait feel free to ask, I'm happy to help you. I'm using this module in a project wrapping every api that I'm using in promises.
The steam object has to keep working like a stream, but we could take a few
of our custom functions and have them return promises.
However I think we need an ansyc Iterator interface. This new interface
could do anything it wants.
On Sat, Sep 15, 2018, 6:23 AM Stefano Cappa notifications@github.com
wrote:
Nodejs 6 has a scheduled eol date at April 19.
So, it could be the right moment to switch to node 8 updating the code.Yes, with babel the "compilation" is very easy.
If you need beta testers when you want to update the code with promises
feel free to ask, I'm happy to help you. I'm using this module in a project
wrapping every api that I'm using in promises.—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
https://github.com/node-serialport/node-serialport/issues/991#issuecomment-421549898,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABlbhEY1KSFB3EZhhkRx1XcGpj7G234ks5ubNUtgaJpZM4Ko7M3
.
Yes, I suppose that it's impossible to promisify a stream
Alright, what do you all think about this? https://github.com/node-serialport/node-serialport/pull/1850
Most helpful comment
Everything in NodeJs is moving to promises, so I think that a new major release non-backward compatible is acceptable.