Open loucadufault opened 3 months ago
After some consideration, I propose these changes to address this:
flush(): Promise<void>
method to wait for any lingering writes.close()
is called, promise to never emit any errors anymore.With these changes, you should be able to acheive a proper cleanup like so:
const xKeys = setupXKeysPanel()
const errorListener = (e) => console.error(e)
xKeys.on('error', errorListener)
xKeys.setAllBacklights(false)
// cleanup:
await xKeys.flush() // waits for all writes to finish
await xKeys.close() // close the device.
xKeys.off('error', errorListener)
The implementation of the generic
write()
method which is called by the variousXKeys
methods (e.g. setting backlights) is asynchronous in nature, yet resolves synchronously before the promise returned by the underlying call tosendReport()
has resolved:https://github.com/SuperFlyTV/xkeys/blob/e9d925e22d184775e252c1991a1105bfedc14311/packages/webhid/src/web-hid-wrapper.ts#L24-L32
Promise rejections are handled by emitting them as
error
events.This forces usage of the API to always have an
error
listener registered for the duration of the program in order for the code to be safe; if the listener is removed at any point, it is possible that a pending promise rejects and emits anerror
event which would be unhandled.This makes it near impossible to clean up an
XKeys
object by calling methods on it such assetAllBacklights()
before un-registering the listeners such that it can be GC'd:A workaround is to keep the listener registered for an arbitrary amount of time to handle any pending promises:
A proper solution would be to allow checking that all
sendReport
promises have settled before cleaning up the device, which would entail making the API methods async.