Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Cannot REMOVE "error" listener from serialport #285

Open
Analogreality opened this Issue · 12 comments

4 participants

@Analogreality

I have some code similar to the following:

var serialport = require("serialport");
var SerialPort = serialport.SerialPort;

var testPort = new SerialPort(port.comName, {
}, true);

serialport.on("error", function (err) {
...
});

That's good and everything however there are two problems:

  1. The 'error' event is subscribed to ALL instances I create of new SerialPort.. a problem when I want each port to have its own error logic.

  2. I can't remove the event from the serialport object. Not even serialport.removeAllListeners() seems to actually work.

Any ideas?

@reconbot
Collaborator

Can you be a little more specific about which errors are called on all instances of serialport? Open errors in specific are emitted on the module's object. Write read and close errors should happen only on the single instance. I wrote some narly tests for read erorrs and it's working alright. Let me know.

@Analogreality

I get the same error, called X times.

I am trying to go through all available ports, connect at a given speed, then send a message. If I get an OK back, I know that the target device understands me at that speed. This is for auto-negotiation of baudrate.

So, I have methods that are on a timer that go through a port, trying a connection, waiting for a timeout (or handling an error such as access denied, which means another app is using that port).

This method executes every X seconds.. to detect the device I open the port and get either an error message, a timeout of the OK message, or the OK message itself.

Since I open the port multiple times, I want it to remove ALL listeners I set up previously for that port.. so before I leave the method I try to testPort.removeListeners("error") and testPort.removeAllListeners().. however it doesn't seem to work. The instanciated testTest port I created with 'new SerialPort' does not listen to an error event.. so removing it does no good. Additionally, there seems to be a more global .on("error") event but that fires on all ports I try to connect on, if there is an error. It too is ignoring the .removeAllListeners() method call..

@reconbot
Collaborator
@Analogreality

Sure, one minute.

@Analogreality
    var serialport = require("serialport");
    var SerialPort = serialport.SerialPort;

    // DO IT TO IT
    var coms = new SerialPort(parent.targetHardwareDevice, {
        "baudrate": parent.targetHardwareBaudrate,
        "parser": serialport.parsers.readline("\n"),
        "disconnectedCallback": function () {
            console.log("DEVICE: Disconnected.");
        }
    });

    coms.once("error", function (err) {
        if (!err) {
            return;
        }

        console.log("DEVICE: ERROR: " + err);   

        coms.removeAllListeners("error");
    });

    coms.open(function (err) {
        if (err) {
            console.log("DEVICE: CONNECT ERROR: " + err);   
        }

        ...
    });
@Analogreality

I intentionally open up the COM port with Putty, blocking nodejs from acquiring the port.

When the previous code is run, I get:

events.js:2817: Uncaught Error: Opening \.\COM6: Access denied

@reconbot
Collaborator

A few things.

You're immediately opening the serial port so you don't need the second open call. It's also why you're not getting an error passed to your callback when you call open. You can either pass the open handling function to the constructor or pass false as the last argument so it doesn't open immediately.

Since you're not passing a callback to the constructor and it is immediately opening the port, the error has no place to go so the module emits it. If you wanted to handle it on the module you could add.

serialport.on('error', function(){});

You also don't need to remove the listener as you're using once.

Hope that helps!

-Francis

@Analogreality
  1. Ah, the implicit default value of reconnectImmediately is True, .. that makes sense.. it errors before the error handler connects.

  2. Ah, I see the .once() part was a mistake.. basically after this method I do NOT want any listeners bound to that object.. or even that object to exist any more.. I will change it to be .on() and then do a .removeAllListeners() call after it, based on a timer.

I will report my findings soon.

@JayBeavers
Collaborator

Let me rewrite your code a little to give some clarity on what's going on:

var SerialPortFactory = require("serialport");
var SerialPort = SerialPortFactory.SerialPort;

var serialPortInstance = new SerialPort(port.comName, {
}, true);

SerialPortFactory.on("error", function (err) {
...
});

I made that change so you can see that you're hooking the error handler on the 'parent object' from which SerialPorts are made (e.g. the Factory). Basically the error design is 'if you hook the factory error handler, it will tell you all the unhandled errors'. If you hook the object like:

serialPortInstance.on("error"...)

then the error will get handled there and not forwarded on to SerialPortFactory.on("error")

So in summary,

  • hook the serialPortInstance.on('error') if you want per instance error handling
  • hook the SerialPortFactory.on('error') if you want global all instances error handling
@Analogreality
@JayBeavers
Collaborator

Take a look, leave issue open -- at a minimum docs should be updated with this information.

@voodootikigod

@JayBeavers Can we close this at this point?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.