2

I'm sending data to the target device using device.sendReport(reportID, dataBuffer) of WebHID, but trying to read the response before it gets ready (i.e) the response takes time to be generated.

For now by setting timeout for 10ms, I'm able to get the response. Would like to know if there are any better solution for this.

CherryDT
  • 25,571
  • 5
  • 49
  • 74
Hema
  • 31
  • 4
  • 1
    Maybe you should use `device.addEventListener("inputreport", (event) => {})`? – Orkhan Alikhanov Jul 27 '22 at 12:07
  • You should probably handle the [`inputreport` event](https://developer.mozilla.org/en-US/docs/Web/API/HIDDevice/inputreport_event). – phuzi Jul 27 '22 at 12:08
  • The function returns a promise, why not just wait for the promise to resolve? – JSON Derulo Jul 27 '22 at 12:10
  • @JSONDerulo Is there a guarantee that data will be available once that promise is resolved? From what I can see it only guarantees that the report has been sent. – phuzi Jul 27 '22 at 12:12

2 Answers2

2

You haven't said how the device provides the response but I assume that it is in the form of an input report. In that case the Promise returned by sendReport() isn't particularly interesting but instead you want to listen for an inputreport event that will be fired at the HIDDevice. If you want you can turn this into a Promise like this,

const response = new Promise((resolve) => {
  device.addEventListener('inputreport', resolve, { once: true });
});
await device.sendReport(...your data...);
const { reportId, data } = await response;

Once the response is received it will be stored in data.

Note that this assumes that the device only generates input reports in response to a request. For a device with more complex communications you may want to have an inputreport event listener registered at all times and process input reports based on their report ID or other factors. HID does not support any backpressure so if you don't have an inputreport event listener registered when a report is sent by the device it will be discarded.

Reilly Grant
  • 5,590
  • 1
  • 13
  • 23
-1

For this type of action you should use asynchronous code. When sending/receiving things to or from a server, this action is a 'Promise' which is asynchronous.

It'll look something like this (using the fetch api as an example):

With callbacks (which are optional)

myFunction = () => {
  fetch('POST', data)
    .then((response) => {
      console.log(response);
    })
    .catch((error) => {
      console.warn(error);
    });
}

With async/await. This is not recommended in most cases, as this assumes that the request will succeed.

myFunction = async () => {
  const response = await fetch('POST', data);
  console.log(response);
}
paddotk
  • 1,359
  • 17
  • 31
  • How is `fetch` the same as `sendReport` the promise returned by `sendReport` will be resolved with `undefined` not really anything useful. – phuzi Jul 27 '22 at 12:15
  • That's fine, then you can just use `.then(() => { // do anything here })`. The idea is that .then() or catch() fires when the server has responded, i.e. that the transaction is completed. This way you don't have to use setTimeout and it fires as soon as it's ready. – paddotk Jul 27 '22 at 12:26
  • Additionally, you can also use `.finally()` which fires regardless of the status of the response. – paddotk Jul 27 '22 at 12:27
  • But `sendReport` doesn't return anything useful when it's promise resolves, I also don't believe that a response could have been guaranteed to be received at that time either. The `inputreport` event should have a listener attached to be triggered when an input report is received instead. – phuzi Jul 27 '22 at 12:28
  • What I'm saying is that you don't need actual response data, but you *always* get a response from any endpoint. You can alos see this in the network tab of the browser's devtools, for example. In other words, the `then` callback is basically like an event listener (promises are not events!) – paddotk Jul 27 '22 at 12:37
  • Does the resolved promise guarantee that data is available to be read? – phuzi Jul 27 '22 at 12:44
  • If there is data given by the endpoint, then `response` in the `then((response => {})` callback will represent that data. This requires the response to be a 'success' type code however (statuscode 2xx). If there's no response data, `response` will be empty but the `then()` will still trigger. – paddotk Jul 27 '22 at 12:46
  • Have you got a link to documentation that states that? What I could [find on MDN](https://developer.mozilla.org/en-US/docs/Web/API/HIDDevice/sendReport) states the promise is resolved with undefined, therefore nothing useful, may be it's out of date though. – phuzi Jul 27 '22 at 12:52
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises This might help. Also be sure to check the docs for whatever you're using to call the endpoint (e.g. fetch, axios etc). – paddotk Jul 27 '22 at 12:54
  • I'm not interested in documentation of Promises. I'm talking specifically about `HIDDevice.sendReport` it does return a promise but the docs state that it doesn't get resolved with any useful data! The question is specific to this function, therefore any answer must also be specific to this function and has nothing to do AJAX/XHR/Fetch/Axios. – phuzi Jul 27 '22 at 12:56
  • Then I'd suggest you rephrase the question, because what you're asking there is about an alternative to setTimeout. You're leading me into an entirely different direction now. – paddotk Jul 27 '22 at 13:04
  • 1
    Not my question and the question explicitly states they are waiting for a reponse to the WEB HID `sendReport` function! Before commenting I checked the documentation to see whether a (useful) Promise was returned specifically from this method. – phuzi Jul 27 '22 at 13:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246815/discussion-between-paddotk-and-phuzi). – paddotk Jul 27 '22 at 13:11