tray icon indicating copy to clipboard operation
tray copied to clipboard

Support multiple qz instances in JavaScript API

Open dsanders11 opened this issue 8 years ago • 7 comments

Right now the JavaScript API only supports a single open connection. We're moving our integration of QZ Tray to a single-page app, and this prevents getting the benefit of long-lived connections that stay open between page navigations. One page might need to be connected to localhost to read a USB scale, another page to QZ Tray running on another machine as a print server. You have to avoid having both of those on the same page, or keeping the connections open long-term, due to the one connection restriction.

It seems technically feasible for the JavaScript API to support multiple connections, although I'm sure it would require a decent amount of refactoring. If it was object-based then you could do things like:

qz.websocket.connect(wsConfig).then(function (connection) {
  connection.setClosedCallbacks(...);
});

And deal with connections on an individual basis.

dsanders11 avatar Oct 08 '17 01:10 dsanders11

Hello David,

As you have mentioned, I would also avoid keeping connections open for the entire lifecycle of the app. You may want to consider opening the required connection when it is needed until this issue is solved.

onurguzel avatar Oct 09 '17 10:10 onurguzel

This appears to be a bug with the JavaScript API. Although our IIFE/singleton made perfect sense when we converted from a singleton Java applet, both the front-end and back-end are written in a way that would allow multiple connections (technically, multiple qz instances).

We need to allow a flag for disabling the singleton behavior, or just disable it entirely. From what I'm reading, this can affect node.js as well. I can't see a downside in this. @bberenz thoughts?

tresf avatar Oct 10 '17 02:10 tresf

@dsanders11 to clarify, this really should have a full new qz instance, not just the websocket. Thoughts welcome.

tresf avatar Oct 10 '17 02:10 tresf

@tresf, yes, a full new qz instance. I was just pointing out the API probably should be object based. Unfortunately don't have the spare brain cycles to give any detailed thoughts.

dsanders11 avatar Oct 10 '17 04:10 dsanders11

We need to allow a flag for disabling the singleton behavior, or just disable it entirely. From what I'm reading, this can affect node.js as well. I can't see a downside in this. @bberenz thoughts?

Well the immediate problem I see is that our api is setup to work statically. That is, qz.action() will always reference the single connection. What's proposed here would turn that into var myqz = new qz(); myqz.action(). Not bad per-say, but this would break all existing code to just up and change. Maintaining that static call style so we don't break existing code and still allowing for a stand-alone object can be done, it just might be a bit messy on the underside.

akberenz avatar Oct 24 '17 18:10 akberenz

@bberenz I noticed that too, but we could still leave qz static UNLESS we provide some form of override, right? I understand the override would need to be in the form of a global and set before the script tag is included in a web page, but it seems possible.

Another option is to allow qz to clone itself, so the default behavior would be to use qz but a method could be used to make a new instance. Unfortunately this may have some GC issues if the original were to die so thoughts welcome.

tresf avatar Oct 25 '17 16:10 tresf

@tresf, just chiming in, but if you're going to be rolling up your sleeves on the JavaScript API anyway you may want to consider using Google Closure Compiler or Babel as a build process. I know Closure has some really nice type-checking support that uses JSDoc tags (which you already have throughout the code) that I've found helpful in the past for catching subtle bugs and writing more robust code. Since both transpile the code to ES5 you can use newer JavaScript features which help make the code cleaner and safe (const, let, etc) without compatibility issues. It does, however, produce non-human friendly output (as it usually also minifies to save space).

Just my 2 cents.

dsanders11 avatar Oct 25 '17 18:10 dsanders11