Node.js callbacks get called multiple times when they throw an exception

It appears the callbacks are called from inside a try … catch block, and any exception they throw will result in more calls to the callback.

var mBlinkStick = require("blinkstick"),
    oBlinkStick = mBlinkStick.findFirst();
oBlinkStick.setMode(2, function (oError) {
  if (oError) {
    console.log("callback with error:", oError);
  } else {
    console.log("callback without error");
    throw new Error("This should not cause another callback");
  }
});

Expected output:

H:\dev\node\pWinStatusBlinkStick>test2.js
callback without error
H:\dev\node\pWinStatusBlinkStick\test2.js:9
      throw new Error("This should not cause another callback");
            ^
Error: This should not cause another callback
    at ...

Actual output:

H:\dev\node\pWinStatusBlinkStick>test2.js
callback without error
callback without error
callback with error: [Error: This should not cause another callback]

I believe you can resolve this in your code by wrapping the callbacks in a setTimeout(…, 0), by replacing this:

    fCallback(arg0, arg1, ...);

With this:

    setTimeout(function () {
        fCallback(arg0, arg1, ...);
    }, 0);

I’ll look into submitting another pull request for this issue tomorrow. Doing this should also resolve the stack exhaustion bug I reported earlier today.

I’ve modified my local copy of BlinkStick’s Node.js code to use…

process.nextTick(function() {
  callback(...);
});

…rather than…

  callback(...);

…where appropriate: not all instances need replacing. (process.nextTick is similar to setTimout, but more appropriate).

This resolves the issue for me: no more double calls to the callback function that report an exception thrown there, but only one call followed by an uncaught exception. If you’ll let me know which branch to apply these changes to, I can get you a pull request for testing.

1 Like